One fact that is agreed upon – is that it takes a lot of time to understand code. Poorly commented code just makes this harder. The challenge that we face, is that developers’ often don’t want to take time away from coding to document, but working with code that is not commented takes more time in the long run.

It is always nice to work on a project that has excellent commenting. However, there have been many projects that I have worked on that have frustrated me with the effort needed in understanding them. When code that I have been writing needs to build on badly documented components, I have sometimes added my own comments. Tragically, I have often not been responsible for maintaining such components and my effort in commenting has gone to waste – as I have not checked them in. Such code often has had three traits.

1. When documentation in needed to understand what is going on.

Code sometimes is so cryptic that many lines of comments are needed to make sense of what is happening. If written well, this code would use clear variables and method names so that the logic is immediately obvious. Doing this not only helps in understanding what the code is doing, but also allows for comments to be used for describing why the code is needed (see item 3).

/**
* calculate the amount of interest gained from a principal of p at a 
* rate of r over y years loop through each year and calculate the 
* new amount based on the rate. set the principal to the new 
* amount for interest compounded annually.
*/
public static float main(float p, float r, int y) {
  DecimalFormat format = new DecimalFormat( "0.00" );
  float a;
  for(int i=1;i<=y;i++){a=p*(1.0+r);}
  p=a;
  return format.format( a );
}

</pre>

The lack of useful variable names and structure in this code prevents it from being easily read, necessitating the use of comments to describe what it does

2. When there is more comment header than actual useful comments.

In the quest for helping developers writing comments quickly, development tools often generate comment headers when creating new classes, methods, etc. While such headers can be helpful, leaving them as-is makes it harder for us to detect the signal (the actual useful comments) from the noise (the automatically generated headers). Instead filling in these headers can make understanding easier.

/**
* @param principal
* @param rate
* @param years
* @return compundedInterest
*/
public static float calcInterest(float principal, float rate, int years) {
  DecimalFormat precisionTwo = new DecimalFormat( "0.00" );
  float amount;
  for ( int year = 1; year <= years; year++ )
  {
    amount = principal * (1.0+rate);
    principal = amount;
  }
  return precisionTwo.format( amount );
}

</pre>

Here we see how automatically generated headers become useless noise when left as is.

3. When it is not obvious **why a piece of code behaves in a particular way.**

One can always figure out what a piece of code is doing (although sometimes it can take a lot of effort). The challenge however, is that if not documented, it is impossible to figure out why the code needs to behave in the way that it does. When writing code, it is therefore important to ask yourself the ‘whys’ and to make sure that it is included in code comments.

/**
* Calculate compound interest for accounting form 2-a.
* We are calculating the interest by using a loop instead of
* principal*(1+rate)^years to show the exact workings of the compounded
* interest calculation
*/
public static float calcInterest(float principal, float rate, int years) {
  DecimalFormat precisionTwo = new DecimalFormat( "0.00" );
  float amount;
  for ( int year = 1; year <= years; year++ )
  {
    amount = principal * (1.0+rate);
    principal = amount;
  }
  return precisionTwo.format( amount );
}

</pre>

An example of a quality comment describing why the code is needed and why it was written the way it was

Other resources

For other tips on improving comments and code quality see the following articles: