Difference between revisions of "Coding best practices"

Line 1: Line 1:
  
{{Template:Working on}}  
+
<span style="font-family:Arial,Helvetica,sans-serif;"><span style="font-size:medium;">There are code standards and conventions available depending on the language you are using and sometimes also conventions adopted for specific&nbsp;collaborative projects. These can be quite complex and out of scope if you are writing a code for your analysis, however there are a few things you can do to make your code much more readable and safer from bugs which are quite simple. In the video linked below, kindly provided by DataTAS, the presenter gives some useful tips which can be applied to any language:</span></span>
  
<span style="font-family:Arial,Helvetica,sans-serif;"><span style="font-size:medium;">There are code standards and conventions available depending on the language you are using and sometimes also conventions adopted for specific&nbsp;collaborative projects. While below we provide a few links to these, here&nbsp;we are just going to focus on&nbsp;some basic tips that can help you making&nbsp;your code more readable and safer from bugs. These can be applied to any language.</span> &nbsp;</span>
+
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">"[https://www.facebook.com/1354624204600925/videos/138577474926767 Reproducible&nbsp;research&nbsp;how&nbsp;to&nbsp;write&nbsp;code&nbsp;that&nbsp;is&nbsp;built&nbsp;to&nbsp;last]"&nbsp;</span></span>
  
=== <span style="font-size:large;">'''Naming'''</span> ===
+
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">It is worth watching the video (the actual presentation is about half of the video ~35&nbsp;minutes) to understand fully how valuable these tips are and also to get a perspective from someone who went from a science background to a commercial software engineering position.</span></span>
  
==== <span style="font-size:medium;">'''Use descriptive names for variables and functions'''</span> ====
+
<span style="font-size:medium;">Below is a list of best practices discussed in the video.</span>
  
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">There is no advantage in using&nbsp;short names for variables and functions, it is good practice instead to use names that are descriptive, even if this will make them longer. Particularly for functions it is good to specify in the name what they do.</span></span>
+
=== <span style="font-size:large;">'''Naming'''</span> ===
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">For example for a function that calculates an anomaly use&nbsp;calculate_anomaly() rather than calc().This also reduce the chances of using a reserved word. NB If you're using an IDE to edit your code then you can easily auto complete the names</span></span>
 
 
 
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Avoid reserved keywords and names of common functions'''</span></span> ====
 
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Reserved keywords are words that are used for special functionalities, they change with the language but usually are used to control the flow of the code&nbsp;as "if", "for", "import" or used for declarations like "None", "True", "global, so they cannot be used to name anything else. Any other word can be used as a name but be careful, in [https://www.geeksforgeeks.org/why-python-is-called-dynamically-typed/ dinamycally typed languages] like Python a variable is evaluated while running the code, it is not declared at the start. This is because a variable&nbsp;name is just a link&nbsp;to an object and so the same name can refer to different objects in the same code.</span></span>
 
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">For example if I have a function called ''mean''&nbsp;and later on in the code assigned a float value to it.</span></span>
 
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">I won't get an error then, but I will when trying to call&nbsp;''mean''&nbsp;as a function</span></span>
 
<syntaxhighlight lang="bash">
 
#For example if I have a function called mean
 
def mean(variable):
 
...
 
return value
 
mean = 45.3
 
#if I try then to call the function I will get an error
 
sst_mean = mean(sst)
 
#as "mean is now referring to the float object "45.3" as i have overwritten the link to the mean
 
</syntaxhighlight>
 
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">mean type of variable can be&nbsp;are some that is still best to avoid, common examples are 'file'</span></span>
 
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">There are also some that can be used as a name,like 'file', 'format', 'int', 'list', 'dict' , but that are already names of&nbsp;existing functions. This will of course also depend on which modules you are using and how you import them.</span></span>
 
 
 
&nbsp;
 
  
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Use consistent naming across the code'''</span></span> ====
+
*
 +
==== <span style="font-size:medium;">Use descriptive names for variables and functions</span><syntaxhighlight lang="bash"></syntaxhighlight> ====
  
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Try to be consistent in the way you name your variables, constants and functions. There are different opionions on what is the best convention:</span></span>
+
*
 +
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Use consistent naming across the code</span></span> ====
  
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">lowercase_words_with_underscores</span></span>  
+
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Avoid hard-coding values</span></span>  
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">CapitalisedWords (also known as&nbsp;CamelCase)</span></span>  
+
*
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">mixedCase</span></span>
+
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Initialising variables</span></span> ====
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">ALL_CAPITALS usually used for constants values&nbsp;</span></span>
 
  
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Whatever you choose&nbsp;try to be consistent, use the same conventions for the same type of objects.</span></span>
 
  
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Avoid hard-coding values'''</span></span> ====
+
=== <span style="font-size:large;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Code structure'''</span></span> ===
  
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Define constant values only once, at the start of the code, or as part of a configuration file , or as arguments to your function or&nbsp;program.</span></span> ====
+
*
 +
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Indents</span></span> ====
  
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">This includes paths, or other string type variables, not just numbers. Defining&nbsp;all these values in one place, &nbsp;will make it easier to update them, without having to chnage a value in multiple places, it will reduce the chnace of errors. It will also make your code more readable, make your intentions clearer and the code will be more generic and faster to adapt for different configurations.</span></span> ====
+
*
 +
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Comments</span></span> ====
  
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Initialising variables'''</span></span> ====
+
*
 +
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Use functions to organise your code&nbsp;</span></span> ====
  
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">You</span></span>
+
*
 +
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Don't&nbsp;Repeat Yourself (DRY) code</span></span> ====
  
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">[https://www.python.org/dev/peps/pep-0526/#global-and-local-variable-annotations https://www.python.org/dev/peps/pep-0526/#global-and-local-variable-annotations]</span></span>
+
*
 +
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">One statement per line</span></span> ====
  
=== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Code structure'''</span></span> ===
+
*<span style="font-size:medium;">Write explicit code</span>
 +
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Keep your files a reasonable length</span></span>
 +
*
 +
=== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Clear flow: try to have only one exit point in a function</span></span> ===
  
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Indents'''</span></span> ====
+
*
 +
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Use tests &nbsp;</span></span> ====
  
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">&nbsp;Some languages like Python enforce indenting, but even where it is not necessary indenting your code can help outlining the code structure. Again try&nbsp;to be consistent either use tabs or spaces, some languages like python have a preference for spaces.</span></span>
 
 
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Comments'''</span></span> ====
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Comments are extremely useful to document what your code is doing. Again you do not need to comment every line, as that might actually made the code less redable. But it is a good practice to have:</span></span>
 
 
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">a block of comments at the start of the code listing author, license,a a date for the last update,&nbsp;what the code does and how to use it.</span></span>
 
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">similarly have a fe wlines of comments for each function or&nbsp;before a coherent block of code in the main program, for example before an "if/else" block.</span></span>
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">It can also be useful starting a&nbsp;code by writing what do you want to do as comments. For example &nbsp;</span></span>
 
<nowiki># Assign arguments
 
# Open data files
 
# Calculate ...
 
# Plot ...
 
# Save output to file</nowiki>
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">&nbsp;In this way you have a draft of your comments and you can work out the best structure, individuate blocks that can be included in a function etc,&nbsp;before you even start coding. It can save you a lot of time.</span></span>
 
 
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Use functions to organise your code / DRY code'''</span></span> ====
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Ideally a function should execute one coherent operation. As none of us it's a software developer we are not suggesting to transform every single line&nbsp;of code in&nbsp;a function, but try to inlcude in a function a logical block of lines. This is particularly true and useful if it's a block of code you might want to repeat in other parts of this same or others programs. Another good reason to enclose a block of code in a function it is to make it easier to add a test. &nbsp;</span></span>
 
 
=== Example of creating several plots using a function and managing different plot option as arguments and with dictionaries ===
 
 
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">DRY code</span></span> ====
 
 
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''One statement per line'''</span></span> ====
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Cramming a lot of instructions in one line of code won't make your code faster, just less readable. It will also make it more difficult to pinpoint what is causing an error if you have a few instructions in the same line.</span></span>
 
 
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Keep your files a reasonable length'''</span></span> ====
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Main message here is to be consistent and descriptive, in the end any conventions aim is to have consistency. Even&nbsp;if you are not using an established convention, being at least consistent across all of your codes will help making them more&nbsp;readable and re-usable.</span></span>
 
 
=== '''<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Order of precedence</span></span>''' ===
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">make your intentions clear even if it is not necessary</span></span>
 
 
=== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Functions'''</span></span> ===
 
 
==== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Clear flow: try to have only one exit point in a function'''</span></span> ====
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">Return example</span></span>
 
 
=== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Use tests &nbsp;'''</span></span> ===
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">It is a good idea to test at least critical parts of your code. You want to be sure that&nbsp;a&nbsp;calculation which is critical to your results, is producing consistent and correct results, no matter what changes you introduce to the same function or&nbsp;other part of your code. No matter how many tests you are conducting it is hard to preview all the possible ways a code can be used and it is often the case that as soon as you sue a different set of data you are going to find some bugs. Every time you fix a bug make sure you are adding a test to capture it. So you will know if accidentally you re-introduce it later on.</span></span>
 
 
&nbsp;
 
  
 
=== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Style guides'''</span></span> ===
 
=== <span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">'''Style guides'''</span></span> ===
Line 122: Line 56:
 
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">[https://cran.r-project.org/web/packages/AirSensor/vignettes/Developer_Style_Guide.html R style guide]</span></span>  
 
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">[https://cran.r-project.org/web/packages/AirSensor/vignettes/Developer_Style_Guide.html R style guide]</span></span>  
 
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">[https://www.datamentor.io/r-programming/reserved-words/ R reserved keywords]</span></span>  
 
*<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">[https://www.datamentor.io/r-programming/reserved-words/ R reserved keywords]</span></span>  
*&nbsp;
 
 
&nbsp;
 
 
&nbsp;
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">References</span></span>
 
 
<span style="font-size:medium;"><span style="font-family:Arial,Helvetica,sans-serif;">This page was inspired by the seminar "[https://www.eventbrite.com.au/e/reproducible-research-how-to-write-code-that-is-built-to-last-tickets-153241109283# Reproducible&nbsp;research&nbsp;how&nbsp;to&nbsp;write&nbsp;code&nbsp;that&nbsp;is&nbsp;built&nbsp;to&nbsp;last]&nbsp;organised by DataTas. A&nbsp;recording is available on their facebook page.</span></span>
 
  
 
&nbsp;
 
&nbsp;
  
 
[[Category:Data induction]]
 
[[Category:Data induction]]

Revision as of 22:19, 28 July 2021

There are code standards and conventions available depending on the language you are using and sometimes also conventions adopted for specific collaborative projects. These can be quite complex and out of scope if you are writing a code for your analysis, however there are a few things you can do to make your code much more readable and safer from bugs which are quite simple. In the video linked below, kindly provided by DataTAS, the presenter gives some useful tips which can be applied to any language:

"Reproducible research how to write code that is built to last

It is worth watching the video (the actual presentation is about half of the video ~35 minutes) to understand fully how valuable these tips are and also to get a perspective from someone who went from a science background to a commercial software engineering position.

Below is a list of best practices discussed in the video.

Naming

Use descriptive names for variables and functions

Use consistent naming across the code

  • Avoid hard-coding values

Initialising variables

Code structure

Indents

Comments

Use functions to organise your code 

Don't Repeat Yourself (DRY) code

One statement per line

  • Write explicit code
  • Keep your files a reasonable length

Clear flow: try to have only one exit point in a function

Use tests  

Style guides