Document Your Code#
Rule 5: Document your code#
I had to hand over my code (semi-english, semi-dutch, unreadable and a complete mess) to real programmers about a year ago and I am still embarrassed by it.
Do you remember what you had for dinner 2 weeks ago? If the answer is no, then documenting your code could be useful not only for others, but also for you.
Document what your functions and classes are doing. In addition, if you have many nested for loops or some very complex code, do not hesitate to put some in-line comments to describe what your code is doing. Overall, do not overdo it by commenting every single line, but rather try to elaborate in the way you structure your code and give names to your objects. This is why Golden Rule is closely tied to Rule 1: Use descriptive names: if you do the latter, the use of the former is much less needed. Here are a few examples to illustrate unnecessary comments or poorly documented code:
1 x = case.one + case.too #sum
2 f = first.second.third.fourth() #gets the data
3 engineeringConcept = 2 * thisAwesomeVariable #multiplication by 2
4 global globalVariable ## define global variable globalVar
5 for i in range(200):
for j in range(300):
for k in range(i,j):
answer = (i + j)**k
6 if a and b or c and d or not b and not c:
print('here')
Did you notice in example 4 that the variable name in the comment didn’t match the code? Clearly the variable name changed after the comment was written. To quote PEP 8: comments that contradict the code are worse than no comments. Always make a priority of keeping the comments up-to-date when the code changes! Over-reliance on comments to document your code can easily result in a lot of extra work; use of descriptive object names can help minimize the number of comments necessary to provide sufficient documentation.
Rule 5 corollary: minimize the use of comments—instead rely on descriptive object names to narrate what your code is doing! In notebooks, you can also use markdown cells before the code cell to describe what follows.
Comparison of bad and good documentation#
The following functions are the same, the only difference is the documentation and object names, can you tell what the function does from the bad example?
Example with bad documentation#
def HF(h,p):
return 0.5*p*9.81*h**2
print('HF(10,1) = ',HP(10,1))
Example with good documentation#
def force_on_wall(wall_height, density_water):
'''Calculate hydrostatic force on a vertical wall.'''
return 0.5*density_water*9.81*wall_height**2
print(f'force_on_wall(wall_height=10, density_water=1) = {force_on_wall(10,1):.1f} N')
It seems pretty obvious that the second example is more clear, and even if you understood what was happening in the first function, the second one probably would have brought you to the same conclusion much faster. And it didn’t take much longer to write the second function.
The example above includes a string immediately after the function definition line (def
), except it uses three quote symbols. This is a documentation string, also known as a “docstring” a key tool for documenting your code. It actually has it’s own PEP guideline (PEP 257 if you are curious), but we will cover this more on the object-oriented programming page. For now, our advice is to get in the habit of at least using a one-line docstring whenever you create function.
def my_well_documented_function():
"""Illustrate a simple one-line docstring---that's it!"""
pass
You should use the imperative verb tense, a command, for example: return, integrate or compute. This helps keep the docstring compact. Compare the following one–liners with the non-imperative equivalents:
Compute area of circle
Computes the area of a circle
And:
Return int number_of_PSOR_coins
Returns the number of PSOR coins as an integer
If told us that it seems silly to write a one-line docstring for such a simple function, especially with such descriptive object names, we’d actually agree with you, especially if you were working in a small group of CEG colleagues, or by yourself. However, there is another benefit of adding a docstring: Python automatically knows to include the first line of a docsting in its built-in help functionality. Try it out here by adding a ?
after the function name (this is a handy trick that works in Jupyter notebooks).
my_well_documented_function?
You can also use the help()
function:
help(my_well_documented_function)