How not to ruin your code with comments

Pawel Kadluczka - Feb 2 - - Dev Community

The road to the programmer’s hell is paved with code comments

Many developers (and their managers) think that comments improve their code. I disagree. I believe that the vast majority of comments are just clutter that makes code harder to read and often leads to confusion and, in some cases, bugs.

A heavily commented code base can significantly slow down the development. Reading code requires developers to constantly filter out comments, which is mentally taxing. Over time, developers learn to ignore them to focus better on code. As a result, comments are not only not read, but also forgotten when related code changes.

Moreover, because all comments look similar, it is hard to distinguish between important and not-so-important comments.

Unhelpful comments

In my experience, unhelpful comments fall into a few categories.

Pointless comments

Pointless comments are comments that tell exactly what the code does. Here is an example:

// check if x is null
if (x == null)
Enter fullscreen mode Exit fullscreen mode

These comments add no value but have a great potential to turn into plainly wrong comments. There is no harm in simply removing them.

Plainly wrong comments

My all-time favorite in this category is:

// always return true
return false;
Enter fullscreen mode Exit fullscreen mode

The most common reason for these comments is to miss updating the comment when changing the code. But even if these comments were correct when written, most were not useful. Similarly to “pointless comments”, these comments should just go.

TODO/FIXME comments

Image description

When I see a // TODO: or a // FIXME: comment, I cannot help but check when they were added. Usually, I find it was years before.

Assuming these comments are still relevant, they only point to problems that were low priority from the very beginning. This might sound extreme, but these comments were written with the intention of addressing the problem “later”. Serious problems get fixed right away.

Let’s be honest - these low-priority issues are never going to get fixed. Over the years the product had many successful releases and the code might already be considered legacy, so there is no incentive to fix these problems.

Instead of using comments in the code to track issues, it is better to use an issue-tracking system. If an issue is deprioritized, it can be closed as “Won’t Fix” without leaving clutter in the code.

Comments linking to tasks/tickets

Linking to tasks or tickets from code is similar to the TODO/FIXME comments but there is a twist. Many tasks will be closed or even auto-closed due to inactivity, but no one will bother to remove the corresponding comments from the code. It could get even more problematic if the company changes its issue-tracking system. When this happens, these comments become completely irrelevant as the tasks referred to are hard or impossible to find.

Referencing tasks in the code is not needed - using an issue tracker is enough. Linking the task in the commit message when fixing an issue is not a bad idea though.

Commented out code

Checking in commented code doesn’t help anyone. It probably already doesn’t run as expected, lacks test coverage, and soon won’t compile. It makes reading the code annoying and can cause confusion when looked at if syntax coloring is not available.

Confusing or misleading comments

Sometimes comments make understanding the code harder. This might happen if the comment contradicts the code, because of a typo (my favorite: missing ‘not’), or due to poor wording. If the comment is important, it should be corrected. If not, it’s better to leave it out.

Garbage comments

Including a Batman ASCII Art Logo in the code for a chat app might be amusing but is completely unnecessary. And no, I didn’t make it up.

Another example comes from the “Code Complete” book. It shows an assembly source file with only one comment:

MOV AX, 723h     ; R.I.P. L. V.B.
Enter fullscreen mode Exit fullscreen mode

The comment baffled the team, as the engineer who wrote it had left. When they eventually had a chance to ask him, he explained that the comment was a tribute to Ludwig van Beethoven who died in 1827 which is 723h in hexadecimal notation.

Useful comments

While comments can often be replaced with more readable and better-structured code, there are situations when it is not possible. Sometimes, comments are the only way to explain why seemingly unnecessary code exists or was written unconventionally. Here is one example from a project I worked on a while ago:

// Do NOT remove this destructor. Letting the compiler generate and inline the default dtor may lead to
// undefined behavior since we are using an incomplete type. More details here:  http://herbsutter.com/gotw/_100/
connection::~connection() = default;
Enter fullscreen mode Exit fullscreen mode

This comment aims at preventing the removal of what might appear to be redundant code, which could lead to hard-to-understand and debug crashes.

Even the most readable code is often insufficient when working on multi-threaded applications. As the environment can change unpredictably in unintuitive ways, comments are the best way to explain the assumptions under which the code was written. 

Finally, if you are working on frameworks, libraries, or APIs meant to be used outside of your team you may want to put comments on public types or methods. They are often used to generate documentation and can be shown to users in the IDE.

Credits: Memes for this week’s post sourced from https://programmerhumor.io/programming-memes

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .