StyleFile: Comments

General advice

Code should be as self-documenting as possible. Your choice of names for variables, methods and classes, and your use of named constants, should all make you code read almost like English. This doesn't render comments unnecessary, but it certainly reduces the circumstances under which they are needed.

Oft-heard advice is that comments should explain code that is difficult to understand. But that advice is wrong. If code is difficult to understand, it should be rewritten so that it can be more easily understood.

Comments in student programs are often included, as an after thought, just prior to submitting the program to the lecturer for marking. They are included "because the lecturer likes them". Too often such comments repeat what the code does, e.g.:

// Add 1 to i
i++;

Not only are comments like these useless, they are damaging to readability since they add clutter to the code.

So what role does this leave for comments? Well, they should be used to explain the intent of the code: what, in high-level, problem-oriented terms, is this piece of code intended to do, e.g.:

// Move on to the next BankAccount in the array
i++;

You should include comments as you go along. Then they incur almost zero effort. By contrast, adding them afterwards, when the code is complete, means that you have to figure out all over again what you were thinking when you wrote the code, which is more time-consuming and likely to lead to inaccurate or vague comments.

You will have seen me practice my own advice in lectures. You will have seen me first write comments about what a method is to do:

/**
 * Returns this time in military time format, e.g.:
 *    0:0:0 is returned as "midnight"
 *    12:0:0 is returned as "midday"
 *    2:30:23 is returned as "2:30:23 a.m."
 *    14:30:23 is returned as "2:30:23 p.m."
 *
 * @return this time in military time format
 */
public String getMilitaryTime()

And then you will have seen me work out roughly how the method will work and record this as more comments in the body of the method, using pseudocode/structured English:

public String getMilitaryTime()
{  /* Work out which part of day this time refers to
      (midnight, midday, morning or afternoon).
    */

   /* Treat midnight and midday as special cases.
    */

   /* Else, convert the time to hours, minutes and seconds.
    */

   /* If a time is in the afternoon, adjust the hours from
      24-hour clock to 12-hour clock.
    */

   /* Assemble and return the components of the military time phrase.
    */

}

Then you will have seen me fill in Java statements below each comment. By this approach, comments are an almost effort-free side-effect of writing the program.

Comments should be placed as close to the code that they explain as possible, e.g. if part of a method body needs a comment to explain how it works, the comment should be just prior to the code in the body, not pulled out into a long preamble prior to the method's header. If comments are close to the code they relate to, there is a greater chance that programmers will keep them up-to-date.

Bear in mind that Java has a utility program called javadoc that can extract certain comments from your programs. It can then create web pages from these comments. The javadoc comments are the ones that begin /** and end */. Where appropriate, make sure you write your comments in a javadoc format. (See below for a little more detail.)

Finally, lay out your comments in a way that is stable under modification.

/***********************************************************
 * For example, the use of boxes of asterisks is common in *
 * code, but it is a bad idea. Consider the extra effort   *
 * this causes you when you change the comment. E.g. if    *
 * the first line is changed to "For example, the use of   *
 * boxes of asterisks LIKE THIS is common in", these two   *
 * extra words have all sorts of knock-on effects on the   *
 * layout. It's this kind of effort that discourages       *
 * programmers from keeping their comments up-to-date.     *
 ***********************************************************/

Commenting class definitions

At the start of the file, include javadoc comments such as:

/**
 * A class that represents dice objects.
 * These are `fair' dice (or as fair as Java's random number generator
 * allows), i.e. when rolling the dice, the probability of each side
 * landing face up is equal.
 * By default, they are standard 6-sided dice, but there is an option to
 * create n-sided dice.
 *
 * @author Derek Bridge
 */
public class Dice

Software engineering organisations may require that you include further comments here, e.g. version numbers, comments about who has modified the class definition and when, copyright statements, etc.

In the course, I require you to include your examination number and email address:

 * @author Derek Bridge 666 d.bridge@cs.ucc.ie

Commenting variables

If your variables have well-chosen identifiers, they might not require any comments. But, where you feel the need to explain their purpose, or special information such as the units (e.g. pounds, pence, inches, centimetres), allowable ranges and constraints (such as uniqueness), etc., here's some advice.

For local variables you can include the comment alongside the declaration, e.g.:

int idNum; // Unique identification number of this bank account.

If these comments are going to run over several lines, then put the comments before the variable declaration:

/* Unique identification number of this bank account.  
   Numbers start at 1000000 and go up by one each time
   a new bank account is created.
 */
int idNum;

For instance variables and class variables, include javadoc comments just prior to the declaration, e.g.:

/**
 * Unique identification number of this bank account.
 */
private int idNum;

/**
 * The number of seconds in a minute.
 */
public static final int SECS_PER_MIN = 60;

Commenting instance methods, class methods & constructors

Here, distinguish comments that come prior to the header and comments that come within the body.

Prior to the headers of methods and constructors, you should use javadoc comments. This is essential for public methods and constructors, but you may as well use them for private ones too.

The format of these comments is:

/**
 * Returns an approximate positive square root of the given number.
 * The result will be within EPSILON of the actual root.
 *
 * @param n the number whose root is to be computed; n must be >= 0
 * @return the approximate square root
 */
public static double squareRoot(double n)

Each parameter (if any) is documented in an @param comment, and the return value (if not void) is documented in an @return comment. (Exceptions should also be documented.)

This would also be a place to document any preconditions you are placing on the values of the parameters to be supplied, e.g. in this example, that n is positive.

Again software engineering organisations might insist that a modification history be included (who changed it when), and you may also want to include cross-references, e.g. to related methods, to the book or paper you took the algorithm from, and so on.

It's important that these javadoc comments, that come prior to the header, explain the purpose of the method or constructor: they explain the what and not the how.

Then, within the bodies of methods and constructors, use comments to explain the how.

Comments within method or constructor bodies will not be javadoc comments. Instead, `paragraphs' of code will be introduced and explained by comments that are delimited by /* and */. The other kind of comment (//) may appear alongside local variable declarations and when helping to show how curly braces match up, e.g.:

/* Find the next empty position in the book catalogue array, if there is one
 */
int i = 0;
while (i < bookCatalogue.length && 
   bookCatalogue[i] != null)
{  i++;
} // end while

(In such a simple fragment of code, the // end while comment is unnecessary, even distracting; but more complex code can benefit from these types of comments.)

These comments should explain the intent, but they should also point out anything unusual. E.g. the example above relies on the short-circuit evaluation of &&, i.e. the second conjunct isn't evaluated if the first conjunct is false. This could reasonably be commented on.