To comment or not to comment? // that is the question
Comments are one of these places where religion meets technology. On one side there are the firm believers that good code is commented code, and on the other side stand the devout to the scarcest commenting chapel.
We can’t discuss expressive code and not talk about comments at some point. Is code expressiveness an alternative to comments, or are the two satisfying different needs? This is the topic I want to address, by showing when comments are useful and complementing otherwise good code.
The reason why I’m spending your time and mine talking about the controversial topic of comments is because I have condensed a fair amount of data about it, coming from:
- the latest occurrence of the Paris Software Craftmanship meetup where one of the topics was an exchange of experience about how to document code. This meetup is a great event by the way. Anyone interested in getting better as a software developer and meeting interesting poeple would spend a good time there.
- the reference book Code Complete from Steve McConnell, which actually dedicates 33 pages to the topic of comments, plus other parts that are related.
- finally my own experience and reflection on this topic.
If I had to sum it up in two sentences
If you’re really short on time, here is the rule that synthesizes it all:
Imagine what you would need to tell to someone who is reading your code, if you were sitting next to them. This is what you put in comments.
And by a strange coincidence, this sentence contains exactly 140 characters. Must mean something right?
Imagine what you would need to tell to someone who is reading your code, if you were sitting next to them. This is what you put in comments.
— Jonathan Boccara (@JoBoccara) April 27, 2017
Indeed, consider the following line of code:
if (!entries.empty()) { ...
Imagine you were telling “Look, here we check that there are some entries before doing the actual work” to the person that is reading your code while you’re setting next to them. What is this person likely to answer? “Thanks, but I can read!”. By chipping in that way, you’re just getting in the way and even interrupting their focus.
The same goes with comments. You don’t want them to repeat what the code says. And making code more expressive is about making the code tell a lot.
On the other side, if the person opens up a big source file and you say: “This file deals with such and such aspects of the program”, then you’d make them a big favor by doing this, because it would take them longer to figure this out just by looking at the code. And the same goes with comments.
Avoid needing explanatory comments
There is another kind of comments: those that explain what the code does. They can carry valuable information for the reader that would otherwise struggle to understand the code. But the piece of code that contains such comments is usually bad code, because it is unclear as it needs to be explained.
The advice that is generally given is to write that piece of code differently, to make it more expressive. And there are a lot of ways to do this, which is why I have devoted Fluent C++ to this topic.
When writing new code, it certainly makes sense to make it tell the story. But I’m not sure that this piece of advice about explanatory comments is realistic in all situations.
Imagine that you’re working on a bugfix and you stumble on unclear code that you struggled to understand. Are you going to interrupt your work and change it? It’s unlikely. Or even log it for a later refactoring? Are you really going to do this for every such piece of code? That can be a Titan’s work to do this systematically. On the other hand, leaving a comment summarizing your findings may be a quick win for everyone.
Plus, some code doesn’t belong to you. Some explanatory comments tell that some code is done this way because way down in the stack, there is something warped that forces us to warp ourselves in symmetry. But you may not have the possibility to access the culprit code! For this reason, explanatory comments have a reason for existence in my opinion.
Now there are quick wins that can do away with some explanatory comments, like getting rid of magic values. Consider the following commented code:
// checks that the level of XP is valid if (xpLevel <= 100) { ...
It has a magic value of 100, which is a bad practice. And the comments clumsily tries to remedy to it. This can can be quickly changed into:
static const int MaximumXPLevel = 100; if (xpLevel <= MaximumXPLevel) { ...
thus making the explanatory comment superfluous.
Talk at the intention level
One thing that dramatically increases the expressiveness of code is raising levels of abstraction. Even though you want your code to be at the right abstraction levels, comments can play a minor role in it too.
In Chapter 9 of Code Complete, Steve McConnell shows the technique of the Pseudocode Programming Process. This consists in starting by writing what you want the code of your function to do in English, in comments. When this is done, then you insert the lines of actual code in C++ (or in any language for that matter) naturally interleaving with the comments. Then you take away some of the comments that are redundant with the code, and leaves those that explain what the code intends to do.
For this to work, the comments should be at the level of abstraction of the function. In other terms, they need to express what the code intends to do, rather than how it implements it. More about the what, the how, and levels of abstraction here.
There is another level of intent that the code can hardly tell: the why. Why was the code implemented this way, and not with another design? If you’ve tried out a design that turned out not to work, this is valuable information for a maintainer of the code (which could be yourself), to keep him off a wrong track. And if someone has actually been on that wrong track, encountered a bug and made a fix, it may be useful to include a reference to the bug ticket in question, in the comments.
If you read Make your functions functional, you’ll see that global variables break functions, by inducing implicit inputs and outputs that the function has access to but doesn’t declare in its prototype. A comment next to the prototype that indicates what interaction the function has with the global variable may be a good indication, until the function gets fixed.
Another intent that is valuable to document in a comment is when, for some (good) reason, you take the conscious decision of going against what usually is a best practice. If you don’t mention anything about it, there is a high probability that someone is going to “fix” it later.
This is illustrated by a bug in the Debian system that had a large impact, when somebody removed a variable that had been left non-initialized “by mistake”. It turned out this non-initialization was participating to the random number generation in the authentication keys. Oops.
“Comment don’t get updated anyway”
This is the strong argument of the anti-comments chapel. And it is true that nothing forces a maintainer of the code to keep the comments in line with the code. This way, the comments may get out of sync with the code, and turn into misleading information. And everyone agrees that no comments are better than false comments.
This is true, but there are a few tips that can reduce the chances of this happening.
The first one is to comment at the level of the intent, because the intent doesn’t changes as much as the actual implementation of that intent.
The second one it to keep the comments as close as possible to the corresponding code. Indeed, comments not being updated do not result from programmers with evil intentions. Sometimes we just don’t pay attention to the comments. Steve McConnell even suggests to stamp variable names into comments, so that when searching for the occurrence of a variable, the comment also shows up.
Finally, the last tip is to add comments at places that don’t change often, typically at the beginning of a file, to describe what this file is about. Even if the implementation in a file can change, the subject this file covers tends to stay stable for a long period of time.
Don't want to miss out ? Follow:Share this post!