Commentary on Comments

This should not be hard – comment the code.  Create documentation so code can be read, understood, and easily modified by both yourself (the original programmer) and others who may follow later on.  Yet most programmers comment their code poorly.  They add terse, often incredibly obvious snippets of description placed to the right of the code, yet neglect to explain important ideas related to program flow, modification of shared variables and use of algorithms or formulas.

Sometime in their early days of programming, many programmers were taught to make sure every line of code had a comment.  This leads to functions that looks like the following…

int rect_area( int width, int height)
{
  int a;                  // ‘a’ is area
  a = width;        // Load ‘a’ with the width
  a += height;     // multiply ‘a’ by the height
  return a;          // return area
}

This trivial code example is an illustration of poorly documented code.  First, every line of code has a comment, but the comments provide no useful information.  Second, the comments are embedded within the code; in particular comments to the right of the code distract the reader from following just the code and possibly finding errors. In a more complex procedure, this style may bury useful pieces of information that might be included in the code or comments.

Did you notice the ‘+=’ instead of the ‘*=’ in the code example above?  This is not a typo.  It is an example of how comments can distract from code debugging.

Finally, the writer has formatted the comments so all of the ‘//’ line up neatly.  Every time the code is changed the comments will need to be re-formatted.  This is a waste of energy that could be used to check on code correctness.

Here is the same trial example of the above code, but commented differently.  (It also has better named variables, but this is a discussion for another blog.)

/**********************************************
* Rectangular Area
*
* Returns area of rectangle as a signed, 32-bit value
* Parameters “width” and “height” are signed, 16-bit values
* Uses standard formula for rectangular area
*    — width multiplied by height
*/
int32_t Rect_Area( int16_t widthInches, int16_t heightInches)
  {
  int32_t areaSqInches;
  areaSqInches = widthInches;
  areaSqInches *= heightInches;
  return areaSqInches;
  }

In my opinion, this code is documented better and is easier to read. The block comment before the function provides all the information needed and the comments do not distract from reviewing the code.

Another common omission by programmers is failure to document the reasons for change of execution flow caused by “if” statements.  This following is an extract of code from a recent project.


// Test if the configuration is auto-timed by reading
//   SAMPLE RATE reg
sampleMode =
   ( NRF_SAADC->SAMPLERATE & SAMPLERATEMODE_Msk);
if( sampleMode == SAMPLERATEMODE_Msk)
{
   // Sample Rate Register Mode bit is set
   // — this means sample rate is controlled by internal timer
   …
}
else
{
   // Sample rate Register Mode bit is clear
   // — so SAADC sampling is controlled by ext. trigger
   …
}

The comments in this extract explain what is tested – checking the auto-timing in the ADC configuration.  The comments do not bother to mention that the register is read and masked; that should be obvious to an nRF52 programmer.  (The expression “NRF_SAADC->…” is the standard method for accessing SAADC hardware registers in Nordic Semiconductor microprocessors.)  The code also includes comments to aid the reader in understanding program flow when the “if” clause is true and when it is false.

Here are a few suggestions for easily implemented commenting practices.

  • Please remember that more comments are not necessarily better.  Comments mixed in with code can be distracting.  If a lot of comments are desired, place them before the function.
  • Every function should have a comment block immediately before the code which provides a one sentence explanation of the operation, a remark about the value returned and a description of the parameters.  If some well-recognized formula or algorithm is used within the function, a note about that is suggested.
  • Comment blocks preceding a function should not be indented and use the full width of the page.  It should begin with a delimiter line starting with “/*” followed by a series of “*” as shown above; it should end with a line containing only “*/”.  This sets it apart from the code.
  • Comments within a function should occupy a full line (or full lines) of text with the same indentation as the code.  Comments should not be placed to the right of the code.
    There are two exceptions:
    – each field of a structure declaration may have a short note to the right of the text.
    – each constant of an enumerated type may have a short note to the right of the text.
  • Most “if” statements should be preceded by one or two comment lines providing a high-level description of what is being tested by the conditional expression.
  • The compound statements following an “if”, “else if” or “else” should begin with one or two comment lines describing the meaning of the test result that causes the compound statement to execute.

My feelings about code comments were spoken better by Donald Knuth (interview with Dave Andrews, BYTE magazine, September 1996)

My shtick is to promote the idea that humans, not computers, read programs. Today, humans can create programs that are faster, better, and more reliable using tools that are getting better all the time. But 98 percent of the world’s people are not computer programmers. I ask programmers to think of themselves as writers, teachers, expositors. When you’re programming, the very act of trying to explain it to another human being forces you to get more clarity. And then later on, you can maintain, modify, and port your programs to other platforms much more easily. Even if your only audience is yourself, everything gets better.”