The big problem with comments is that they need to be maintained. When the code changes, the comments need to change with it.
The never, ever happens consistently.
So soon you have the "man with two watches" problem. The code says one thing, and the comments say another. You could fix it, and sometimes you spend that time, but inevitably you also stop reading the comments, since they're not reliable.
I've never seen this not happen in comment heavy projects.
> The big problem with comments is that they need to be maintained. When the code changes, the comments need to change with it.
> So soon you have the "man with two watches" problem. The code says one thing, and the comments say another. You could fix it, and sometimes you spend that time, but inevitably you also stop reading the comments, since they're not reliable.
When you think about it, function and variable names are comments. Should we not use those because they need to be maintained with the code?
My main solution is to use good function and variable names.
Including - and I had some resistance to this - breaking out a variable or function solely to give something a name that needs describing.
This way you have one source of truth. It can be wrong, but you only update it once, and it never conflicts with itself.
I understand what you mean by "function and variable names are comments". We do use them to describe what the code does. Still, they are actually code :)
Redundancy helps to spot errors.
When I see code like
// add vertical scroll bar
addHorizontalScrollBar(...)
I _know_ something is wrong.
Did the comment get out of synch with the code?
Or the developer copied-and-pasted the wrong function?
Or the function itself is misnamed?
I don't know! Let's investigate... and fix whatever happens to be erroneous!
But when I see just
addHorizontalScrollBar(...)
all I know is that a horizontal bar seems to be added (provided the function name reflects its... er... function).
I don't know whether it was intended behaviour.
If it has not been, nothing indicates this at all.
I've actually caught real bugs this way, multiple times.
> My main solution is to use good function and variable names.
The problem with this is that it isn't actually solution. A name can't contain much that's helpful to know about a thing, which should be obvious given how much prose and narrative everyone produces and consumes. The program itself can only tell you what. Names can sometimes hint at intent, but they they're not very good at it (given the incentive for terseness). Comments are good for explaining the "whys" for a thing as well as intent. Those are important things to know when debugging a problem or trying to enhance something.
Comments shouldn't be thought of as the one thing you need to look at to understand some code. You really have to look at a whole constellation of things (comments, implementation, commit history, tribal knowledge) and synthesize them. When you take that approach, even out of date comments can be more useful than no comments.
> I understand what you mean by "function and variable names are comments". We do use them to describe what the code does. Still, they are actually code :)
They're not any more code than comments are. Run an obfuscator and change all names to random strings and everything will still work fine, just like if you ran a program to strip out comments.
I agree with elements of both sides here but I do think there's one important difference with function and variable names, which is that they have to match between definition and usage.
If you refactor a function or variable to do something different, often it becomes obvious at the calling/usage site that something isn't quite right any more and the name gets fixed. Just having more instances of it gives you more opportunities to realise you need to fix the name.
It's absolutely not foolproof, you can obviously still have them get out of sync. I do find it's rarer, though, personally.
This is something you can quickly see with Git. If the comment lines are older than the code lines you can at least start with the assumption that the comment might be outdated.
That’s more useful than dealing with stale documentation which can also be outdated. At least with code comments you have contextual proximity.
1. Iterate through all blocks of comments.
2. Determine if there have been updates within the block of comments first (one line of three updating, for example).
2. For each block of comments, find the proceeding block of code.
3. Compare the last update of comments to the last updates of the code.
4. Warn the user when it's over a threshold.
In my view there's no machine or rules that will automatically make your code readable against your will. If two people express themselves differently in prose, perhaps one better than the other, the same will be true in code, with or without comments.
This is an argument to keep the comments short and to the point (preferably one-liners for code paragraphs, longer for functions themselves), not to skip them altogether. Then both checking them and updating them becomes less of a burden.
I even find "man with two watches"useful. When I see it, I _know_ that something is wrong here, and it's worth checking. Most of the time the comment is found to be "buggy" (and gets updated), but I have found quite a few real bugs in the code this way.
The never, ever happens consistently.
So soon you have the "man with two watches" problem. The code says one thing, and the comments say another. You could fix it, and sometimes you spend that time, but inevitably you also stop reading the comments, since they're not reliable.
I've never seen this not happen in comment heavy projects.