Robert C. Martin's Clean Code book has a great section on comments:
- The proper use of comments is to compensate for our failure to express ourself in code. Comments are always failures. We must have them because we cannot always figure out how to express ourselves without them, but their use is not a cause for celebration. So when you find yourself in a position where you need to write a comment, think it through and see whether there isn’t some way to turn the tables and express yourself in code.
- The older a comment is, and the farther away it is from the code it describes, the more likely it is to be just plain wrong. The reason is simple. Programmers can’t realistically maintain them.
- Comments Do Not Make Up for Bad Code! One of the more common motivations for writing comments is bad code. We write a module and we know it is confusing and disorganized. We know it’s a mess. So we say to ourselves, “Ooh, I’d better comment that!” No! You’d better clean it! Clear and expressive code with few comments is far superior to cluttered and complex code with lots of comments. Rather than spend your time writing the comments that explain the mess you’ve made, spend it cleaning that mess.
```
// Bad:
// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))
// Good:
if (employee.isEligibleForFullBenefits())
Sometimes, comments are a justification. Sometimes you have to do things that seem like the wrong thing to when reading the code (like sending a POST request instead of a GET when a GET is clearly more appropriate, but you have to talk to a poorly-written API that will only respond to POSTs on that route). Comments help rationalize that decision for the next guy.
I also find TODO comments quite helpful. It requires far fewer brain cycles to process a TODO comment than to parse the code, figure out what it's doing, and make an assertion that it's incomplete.
Comments can also make code much more approachable to junior programmers, who may not have heard of principles like Tell Don't Ask, or Composition Over Inheritance. When I'm working with a junior dev, I find that comments usually reduce the number of interruptions I receive that are along the lines of, "Hey why did you do this thing this way?"
Really, it's just not a good idea to make sweeping generalizations like, "Comments are always failures". The real world has time and budget constraints, and comments are sometimes the most effective way to satisfy those without screwing the next developer to read the code.
If you're systematic about the syntax of your TODO comments, you can also 1) jump to them, 2) traverse them in order of priority, 3) automatically surface changes to the list of TODOs as comments in commit messages, and 4) use commit hooks to refuse to commit code with overly severe TODOs to certain branches.
If you mean that they won't maintain them, well, I agree. Sometimes I fail to do so myself - but that's my laziness, not because keeping a comment up to date is actually difficult. The fact that programmers can be lazy is why we put processes in place to catch ourselves - code reviews, code style enforcement, and so on.
Because, realistically developers will be lazy. For example:
"Sometimes I fail to do so myself - but that's my laziness"
> code reviews
So, here is the thing, "programmers can be lazy." Programmers can also miss things. Code reviews don't catch everything.
So, when someone says "programmers can’t realistically maintain them", they are being realistic. Really. It's great to be hopeful, but the simple fact is, you can't trust that comments are maintained.
Couldn't you use the exact same argument to say that it's realistically impossible to maintain a high quality, readable codebase, so why bother trying?
There's nothing that intensely difficult about implementing processes that keep at least the vast majority of comments up to date. If you don't feel like it, or your organisation doesn't have the will to enforce it, then fair enough. That's not the same as it being impossible.
I'll add comments to already existing bad code, describing the results of my archeology.
I should refactor. But sometimes it's not feasible when you're in a hurry and the area has no unit tests to prop it up. Adding a tag "TODO: CLEANME" or something similar works as a reminder.
This actually works even in natural language. If you think about it for a moment, sometimes what you thought isn't necessarily what you said, and most likely you will, either intentionally or unintentionally, resort to other means to communicate the thought, such as facial expressions, what you are wearing, and so on.
I think it's a common fallacy to believe that it is our failure when we can't express a particular thought. The language itself, be it human or the far more restrictive and qualitatively restrained computer version, is deficient in many regards.
It seems to me that the Haskell wiki's recommendations on commenting align pretty well with Uncle Bob's. Personally, I'm glad for this. On this topic, I agree with both Uncle Bob and the Haskell wiki.
- The proper use of comments is to compensate for our failure to express ourself in code. Comments are always failures. We must have them because we cannot always figure out how to express ourselves without them, but their use is not a cause for celebration. So when you find yourself in a position where you need to write a comment, think it through and see whether there isn’t some way to turn the tables and express yourself in code.
- The older a comment is, and the farther away it is from the code it describes, the more likely it is to be just plain wrong. The reason is simple. Programmers can’t realistically maintain them.
- Comments Do Not Make Up for Bad Code! One of the more common motivations for writing comments is bad code. We write a module and we know it is confusing and disorganized. We know it’s a mess. So we say to ourselves, “Ooh, I’d better comment that!” No! You’d better clean it! Clear and expressive code with few comments is far superior to cluttered and complex code with lots of comments. Rather than spend your time writing the comments that explain the mess you’ve made, spend it cleaning that mess.
``` // Bad:
```