In-code documentation or comments are vital in helping engineers understand a system and work efficiently. However, many software engineers avoid writing comments with the following excuses:

  • "Good code is self-documenting."
  • "I don't have time to write comments."
  • "Comments get out of date and become misleading."
  • "The comments I have seen are all worthless."

These excuses are all myths. Let's bust the myths.

Good code is self-documenting.

  • A significant amount of design information cannot be represented in code. For example, the justification behind a particular design decision; or the edge cases. One of the purposes of comments is abstraction, i.e hiding complexity. There is no abstraction if users must read the code to use it.
  • Using name of the method to replace comments usually results in long names such isLeastRelevantMultipleOfNextLargerPrimeFactor.

I don't have time to write comments.

Writing comments is one kind of long-term investment. It often doesn't have an immediate impact; in the long run, it helps you and your team work more efficiently.
Writing comments doesn't take a lot of time. I estimate that without writing comments, engineers spend only around 10% of their development time typing code (as opposed to designing, compiling, testing, etc.). Writing comments won't add much burden to the development time.

Comments get out of date and become misleading.

Keeping comments up-to-date doesn't require a big effort. In general, significant changes to comments or documentation are necessary if the code base changes a lot, and the code change will take more time than documentation changes.

All the comments I have seen are worthless.

This problem roots in the way we write comments, not the comment itself. And it is solvable.

How to write solid comments

The ultimate purpose of comments is to capture information in the designer's mind that can't be represented in the code.

  1. Don't repeat the code
// Loop through the vector and write out the values.
for (int i = 0; i < a.size(); ++i) {
  std::cout << a[i];
}

Comments should provide hidden details in code. 2 types

  • lower-level comments
    This type add precision to the code:
    • unit of variable.
    • boundary is inclusive or exclusive.
    • if a null value is permitted, what does it imply?
  • higher-level comment
    This type provide intuation to help reader understand the overall intent and structure of the code. Ask yourself: what is the simplest thing you can say that explains everything in this code?
  1. Avoid comments likely to become outdated
// This is new implementation of Quicksort.

// the foo(), bar() function call myFunc() 

If the comments capture a fact at a particular point in time, include the date time to ease the future reader.

  1. Define unfamiliar terms.
    When documenting a variable, think nouns, not verbs, i.e focusing on what the variable represents, not how we manipulate it.

  2. Specify exact ranges and what happens if a value falls beyond that range.

Bad:

// P is an integer up to 100.

Good:

// P = [1, 2, ..., 100].

// P must be a positive interger <= 100. Otherwise, return -1.
  1. Don't describe implementation details in interface documentation.
    Ask yourself: do users need this information to be able to use this piece of code?

  2. Add useful examples.