I hear people say comments should explain the why, while it isn't 'wrong' per se, I can't remember that being the primary reason for my comment. Below are some comments I have written in my current codebase. These aren't the only type of comments I write but this style is different from what I hear people suggest.
Comment Non-Idiomatic Code
This comment is in my FontLoad function which puts glyphs in a font file into a bitmap so I can convert it to a texture and render it to screen. This comment is at the start of the loop that iterates through all the glyphs in the file, glyph is a 32bit int.
//Skip Control Code and Private Use Area
if (glyph < ' ' || (glyph >= 0xE000 && glyph <= 0xF8FF) || (glyph >= 0xF0000)) {
If I wanted to explain the why, I would have written control codes are invisible and private-use glyphs aren't used in the program, but clearly, that's not what I wrote and not the reason for my comment.
What's unusual here (or non-idiomatic) are the literals E000, F8FF, and F0000. Usually, I'd name literals, but they were used exactly once in the entire program. I didn't want to spend 3 lines creating constants that would be used exactly once so instead I wrote a comment. The 'why' isn't worth anything here. The program won't misbehave if we include control codes or private-use glyphs. If this function was copied into a new project it'd be confusing to see a comment suggesting private area fonts aren't used when they are. I stick to explaining the literals because that was the only unusual part of the line.
Later on in the same function, I wrote if (w && h) { //has pixels
It's very weird to see that if statement and would cause many people to wonder if there's a typo and why that if statement exists. It may be surprising to hear glyphs in a font file can have no pixel data. However, the comment is extremely clear in the context of the rest of the function. It suggests there is a case where a glyph has no pixels, and in a function loading fonts to a bitmap we wouldn't need to attempt loading a glyph with no pixels.
This next comment is in a compare function for a struct I implemented.
return v < 0 ? 1 : v ? -1 : 0; //Want descending so we use -1 instead of 1
The struct is only visible in one file and only used in one function. That function doesn't return the struct or accept it as a parameter. I have an array of that struct which I call sort on and I need it to be in descending order. Usually, when you write a compare function you have it in ascending order, and typically the object is used in more than one function. This case is weird and I wanted to leave a comment to show the descending order is intentional.
What If The Comment Is Too Short Or Not Good Enough?
Assuming the code is fine and the variables are named well, you could still run into hard to understand non-idiomatic code. If that's the case I highly recommend putting a multi-line comment outside or at the start of the function explaining what the function should do in full. Having an explanation with code in the middle makes it hard to understand. Having code with explanations in between makes the code harder to read. If the function is implementing an algorithm or a spec link it.
If you can't understand what the function should do then you really can't change it, at least not without guessing which is something you should never do. Alternatively, you could try:
- Have the function/class only visible in one file so people generally don't need to interact with it.
- Mark the function as deprecated and recommend alternatives.
- Improve tests/examples so a person can look at usage.
- Change variable names to be more friendly to people who aren't familiar with the domain.
- Have books/reading material for that domain linked to at the top of the file.
- State why the algorithm in the function is chosen. Perhaps people are only looking at the function to see what it does. If that's the case stating why the algorithm is chosen may be good enough.
- Refactor the code and write unit tests. This will make it less likely for a change to break the system or waste hours of debugging time.
If all of the above fails and you understand the code but your coworkers do not, I guess you could comment the why. But I can't imagine the success rate if the above fails.
I generally write experimental code that is often thrown away. Usually, the code isn't perfect or idiomatic all the way through. I found the above style to be clear and not cause confusion whenever comments become stale. These short comments have been useful to me since they're short enough not to take me out of the flow of reading code.