Refactoring Code Comments Can Increase Maintainability

The assertion of this post is that code comments are a smell.  Creating obvious, readable code is more maintainable that unreadable code that is heavily commented.

Matt Hinze is teaching Agile Boot Camp, part 1 this week, and one of his lessons is about code readability.  He spoke about code comments being a smell.  When something smells, it doesn’t guarantee that it is rotten, but it does create the need to examine more closely to see if any bacteria is beginning to invade the codebase.  In this case, code comments may be a smell or harbinger of maintainability problem.

Let’s get the first straw-man out of the way.  Taking an existing codebase and merely deleting all code comments does not make a system more maintainable.   I’m not suggesting you do this for your existing system.  This course of action would be foolish.

When developing code, sometime one finds that a section is less than obvious.  When an ambiguous section of code is discovered, the wrong course of action is to add a comment describing what it does.  The better option is the refactor the code to make it more obvious. 

Problems with code comments:

  • Code comments are not compiled
  • Code comments are not tested
  • Code comments are not verified frequently
  • Out-of-date comments have negative consequences
  • They are likely to remain when the code changes

How, then, do we communicate to the maintainer the purpose of code that is less than obvious?  Consider the following example that takes some ambiguous code with comments and refactors away the comments.

public class SpeakerClickReport
{
    public int Total { get; set; }
    public int IndTotal { get; set; }

    // get ration of individual clicks to total clicks for a given speaker.
    public int GetRatio()
    {
        //Total clicks for all speakers equaling 0
        if (Total == 0) return 0;
        //take clicks for this speaker and get the percentage compared to Total for all speakers
        return (int) (100.0*IndTotal/Total);
    }
}

Notice that the comments help to communicate the intent of the code, although it isn’t clear what this code is doing.  When this code changes, these comments will be out-of-date.  Let’s consider a refactored example and compare the readability.

public class SpeakerClickReport
{
    public int TotalOfAllSpeakerClicks { get; set; }
    public int NumberOfIndividualClicks { get; set; }

    public int GetPercentageOfTotalForIndividualSpeaker()
    {
        if (TotalOfAllSpeakerClicks == 0)
        {
            return 0;
        }

        var ratioOfTotal = (double)NumberOfIndividualClicks / TotalOfAllSpeakerClicks;
        var percentFormOfRatio = (int) Math.Round(100 * ratioOfTotal);
        return percentFormOfRatio;
    }
}

Notice that none of the code comments are left.  In their place are:

  • More obvious variable names
  • Whitespace used to divide sections
  • More intermediate variables to describe single-step decisions and calculations
  • Public API more obvious
  • Obtaining return value before actually returning it

The second example is more maintainable than the first because as code is refactored, the comments are actually embedded in the code, not ignored by the compiler.  As class members are renamed and moved around, the contextual information will remain and be refined.  The risk of the commenting information being out-of-date and useless is mitigated.  In short, embedding more information into the source code creates more maintainable code.

Code will be read many, many more times than it is written.