In Praise of the Lowly Comment

The compiler removes them completely. The computer ignores them. Some developers think we should do away with them entirely. But in the grand scheme of software development, I personally think they have a very important part to play. What are they? Comments, of course. Now, that's not to say that all comments are created equal, or that you should just sprinkle your code with comments without thinking about what you're doing. But in my experience, good developers recognize that comments are a useful tool, and employ them to make code more clear and maintainable. With some practice, you can do the same.

Dysfunctional Comments

Let's sneak up on the notion of good comments by considering the other kind first. There are some comments that I think you can (and should) safely eradicate from your code. These include:

The tracking comment, listing who modified the code, when they did it, what they had for breakfast, and so on, in some sort of carefully formatted block (generally with a border made up of asterisks). You have a source code control system, right? Let it keep track of this sort of thing and don't bother repeating it in the source code.

The "what" comment, repeating the code itself in English. You've probably seen code where every line had a comment, and i++ was painfully annotated with "increment the counter variable." You should presume that anyone reading your code understands the syntax and leave these comments out, unless you're actually writing a tutorial for beginning developers.

was painfully annotated with "increment the counter variable." You should presume that anyone reading your code understands the syntax and leave these comments out, unless you're actually writing a tutorial for beginning developers. The long explanatory comment far removed from the code it is purportedly explaining. I have seen developers stick entire readme files into comments, discussing the overall architecture and logic of their application. The problem is that the architecture and logic gets revised and the comment doesn't, and out of sync explanations are worse than no explanation at all. This sort of overview belongs in external documentation, where it has some hope of being maintained.

In general, if a comment isn't going to bring lasting value to the code - leave it out.

Why Not Leave Them All Out?

Some developers look at the problem of comments going out of sync with the code and see an insurmountable issue. Others (and these tend to be among the best and brightest developers) proudly boast that they write "self-documenting code." In either case, their prescription is the same: code with no comments at all.

While the notion of self-documenting code is seductive, in the end, I just don't believe it. Clarity in code is worth striving for, but as I've said elsewhere, this software stuff is hard. No matter how crisp your naming conventions, no matter how perfect your choice of implementation language, no matter how much effort you put into refactoring, there is going to come a time when you need to do something clever in your code to meet a business need. And the more clever the code, the less self-documenting it will be. If you leave it undocumented, you risk a maintenance nightmare when you go back in six months to make an improvement and can't quite remember what you were doing in the first place.

White Hat Comments

So if code needs comments, but not all comments are good, how do you write good comments? In general, there are at least four kinds of comments that I think are worthwhile in most source code:

Placeholder comments

Summary comments

Intent comments

Rocket Science comments

The Placeholder Comment: A String Around Your Virtual Finger

Some commands exist mainly to remind the developer to do something (or not to do something). By convention, most of us tend to introduce these with a single word in all caps: TODO, BUG, POSTPONE, HACK, UNDONE, and so on. Such comments act as little bookmarks in the code, preventing the need to cover your monitor with sticky notes as you have work in progress.

Placeholder comments are most useful when you're working with an IDE that will collect them automatically for you into a virtual to-do list (as most of them will these days). If you sprinkle your code with TODO labels as things occur to you, and you have a window open showing all the TODO lines in the code, you may be able to get by with relatively little process for tracking bugs and features (though your manager might complain about this theory). Such comments should generally be short; if there's a bug that takes a paragraph to explain, it belongs in a more formal bug-tracking system.

If there's any chance of your source code being publicly released (or even privately released to selected customers), you should do a careful review of placeholder comments to make sure that you're not shipping something that will embarrass you. You can take a look at Google Code search to find people who didn't follow this rule of thumb.

The Summary Comment: Compensating for Tiny Brains

I'm not a fan of explaining every line of code with a line of comment that says exactly the same thing. But summary comments, that explain an entire block of code at one time, are a somewhat different animal. Rather than explain ten lines of code individually, a summary comment might say something like "Sort the customer list by age of oldest invoice and display" or "Now center the uploaded graphic on a white rectangle that fills the target area."

Most likely, there isn't any single line of code in these blocks that would be difficult to understand on its own. But by summarizing the code, you can make it easier to understand the overall flow of the application. Given the choice between reading 100 lines of code or ten lines of summary comments, the latter can be much more efficient. Depending on your IDE, you can make the process even easier by coloring the comments so that they stand out visually.

To a certain extent, good coding practices can obviate the need for summary comments. If you keep methods very short and use descriptive names for the methods themselves, then the naming can become the comments. But the more procedural the code gets, the more likely you are to find that some sort of summary commenting can serve as a useful road map to what's going on.

Intent Comments: Why is This Code Here?

With intent comments, instead of explaining how code works or what it does, you explain why it's there in the first place. A typical intent comment is longer than a summary comment, and applies to a larger section of code - an entire object, or a substantial piece of procedural code. You might explain in an intent comment, for example, that the EnahncedTableAdapter class is necessary because the standard TableAdapter doesn't include transactions or interface with your company's custom configuration classes.

Intent comments can be very difficult to write, because they force you to actually think about what you're saying; they're not a mechanical process. If you have a good functional spec for your application, you may be able to reuse some of it for these comments. In any case, they're worth the effort, because they pay off when it becomes time for maintenance programming. Intent comments can help you very quickly come back up to speed on code that you haven't touched for a while (or that someone else wrote) and easily locate a section that you need to work on.

Rocket Science Comments: Sometimes it is.

Finally, you will occasionally hear writing code dismissed as "well, it isn't rocket science." The problem is that sometimes, in fact, it is rocket science (or pick the metaphor of your choice for difficult intellectual pursuits). Multi-threading, database transactions, optimization algorithms, fancy graphics processing...there are plenty of things that you can do in code that won't be immediately obvious to the average developer, even if they understand the basic syntax of the language that you're using.

In such cases, you need to write comments to explain the tricky code. You'll find many people to tell you that having code this tricky is a bad thing, and that the right answer is to rewrite the code until it's not tricky. But sometimes, your code will be as simple, as direct, and as clear as it can be - and it will still be tricky, just because of the nature of the problem. In those cases, you can't assume that every future reader of the source code will be as brilliant as you are today. (Future readers, of course, include you three weeks from now). The simple fact is that such sections of code need comments.

Rocket science comments might be summary comments or intent comments, but they need to be written with particular care. It doesn't help if the comments are just as difficult to understand as the code itself. You need to strive for a tutorial voice that explains any difficult concepts, possibly with further reference material. At times, you may find that such comments are longer than the code they apply to. That's fine; writing a long comment now is better than wasting hours six months from now trying to decipher your brilliant code.

It's All a Matter of Discipline

Why do developers write bad comments, or spend so much energy trying to justify a "no comments" policy? I think it's because writing good comments is hard, and maintaining them (so that the comments continue to reflect the actual state of the code) is hard too. But trying to avoid development work by skimping on comments is like trying to avoid housework by skimping on the daily cleanup chores. Over the long run, you'll be much better off if you develop the discipline to write crisp, clear, useful comments in your source code - comments that will actually help you and other developers make sense of the code when it's time to work on it again. In this business, anything you can do to help yourself out in understanding complexity is worth the effort.

About the Author

Mike Gunderloy is the Senior Technology Partner for Adaptive Strategy, a Washington State consulting firm. You can read more of Mike's work at his Larkware Web site, or contact him at MikeG1@larkfarm.com.