My take on commenting code - Explain why, not how

Keff - May 13 '22 - - Dev Community
// This is the start of the article
Enter fullscreen mode Exit fullscreen mode

Ohh damn, couldn't have figured that one out if it wasn't for the comment...

Just kidding, though many code comments I see are as useful as a comb to a bold person.


👋 Hey there! It's been a while since I've written anything here. Hope you're doing fantastic!

Just wanted to come back to write a bit, so I will start with a little rant about code comments, as I see many new developers find this confusing and filled with confusion.


PD: Before continuing I want to make it clear that I'm talking about code comments, not documentation comments, which can be useful.

Code comments are intended to add more context to your codebase, in case the code itself is not enough (but normally code should be enough).

I want to make a big emphasis on "when the code is not enough", as you should aim to write clear and readable code first, then refactor, refactor, and then if still needed provide a comment to further explain it.

Also, when writing code in an existing codebase, either at work, on an open-source project or whatever. There might be a standard or convention in place, which might require you to write comments. This must be respected and followed unless you have the authority to change it.

Let's break down some myths

You should comment on everything

const age = 21;            // Specify the age of the user
const name = "Bob";        // Set the name of the user
const yearsLeft = 84 - 21; // years of life left
const bananas = 'yum';     // I like bananas
Enter fullscreen mode Exit fullscreen mode

This is one I hear quite a bit. Some of the interns I've had were shocked when I told them to not focus on commenting code but instead focus on trying to write readable code.

This was because their teachers told them that they should comment on everything, all of the time.

It's quite an extreme way of looking at comments, in this fashion you will fill your code base with comments that just say "// Assign a name to the user" and so on.

You should not comment at all

[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]])
Enter fullscreen mode Exit fullscreen mode

This is the opposite side of the spectrum, and in my opinion, is also really extreme. There are a few cases where commenting code is really useful. Or to understand code like the example above, using JSFuck. (It runs alert(1))

For example, I will expand on this, explaining WHY a piece of code is needed.

In my case, I strive to write as few comments as possible, and if I comment something I usually explain "WHY" not "HOW".

For example, instead of writing:

// Resets the canvas
canvas.reset(); 
Enter fullscreen mode Exit fullscreen mode

You could put it this way:

// We reset the canvas here so we don't draw over the currently rendered drawing 
canvas.reset();
Enter fullscreen mode Exit fullscreen mode

 Where to put comments?

This is subjective, and depends on each language, project and our own standards. But generally comments:

  • should go above the code
// Comment
const code = "";
Enter fullscreen mode Exit fullscreen mode
  • or after the code in the same line.
const code = ""; // Comment
Enter fullscreen mode Exit fullscreen mode

I've also heard people put the comments after the code, which for me is a weird place to put them, as code flows from top to bottom, it makes no sense to me to put the comment afterwards. But again, this is up to you and the codebase standards and conventions.


Now let's lay down a list of some of the pros and cons:

Pros

  • Adds additional context to your code
    • For example explaining why we might need that piece of code in a particular place
  • Helps to create a mind map (in some cases)

Cons

  • Adds noise
    • Can make your code look messy, making it more tedious to read through the actual code
  • Adds another dependency
    • You'll need to keep them updated as the code changes, otherwise it can be confusing as hell. Comments can become outdated rather quickly
  • You will tend to read the comments first, then the code, which might condition you.

 Let's look at some examples

 Bad comments (or useless)

class User {
  // Returns the name of this user
  namedWhat() {
     ...
  }
}

const name = user.namedWhat(); // Get the user's name

// Adds item to list if it's not present in the list
addItemToList() {
    if (this.item && !this.items.some((it) => it.id == this.item.id)) {
        this.items.unshift(this.item);
    }
}
Enter fullscreen mode Exit fullscreen mode

These comments offer little to no value at all, they just add noise. Naming methods and variables correctly offer way more value than comments similar to the ones above.

The above example could be made a lot clearer by renaming some methods, and changing some comments so they explain why we need it instead of what it does (that can be explained by the method name)

class User {
  getName() {
     ...
  }
}

const name = user.getName(); 

// this method is needed because if this.items does not contain this.selectedItem, the selector will not display the selected item. 
// By using this method we ensure the selected item is displayed
ensureSelectedItemIsOnList() {
    if (this.hasSelectedItem && !isSelectedItemOnList()) {
        this.items.unshift(this.selectedItem);
    }
}
Enter fullscreen mode Exit fullscreen mode

Renaming the addItemToList method to ensureSelectedItemIsOnList, and creating methods to better explain the code, and also adding an explanation on why this method is needed, makes it a lot more clear. We know, by the method name, that it will ensure that the selected item is on the items list. Then the comment adds a bit more context on why it's needed: "Making sure the selected item appears on the selector, even if it's not in the loaded list of items."

You might be thinking

How can the above comment benefit us as developers?

Well, it's quite simple, let's say you work on the piece of code shown above, you build the selector, find the error with the selected item not displayed if not contained inside items. You fix it and add the comment to explain why you added that piece of code.

Then you don't return to that code in 6 months or a year, and then you or another developer need to build a new selector. And of course, you build it from scratch and stumble across the same bug. Then you go to the original selector to see what is different. Then you see the comment which kindly explains the solution to the bug.

If the comment was not there, you would have to once again solve the bug on your own, which can take no time at all or quite a bit of time, depending on the bug.

So, by having the comment, it makes it quite straight forwards. Believe me, the code above is extracted from one of our projects, and that comment has saved us a whole lot of work.

Summary

We've covered some common myths and misconceptions around comments, and we've seen examples of useful and useless comments. And explained why they're considered useless and useful.

 Key concepts to take away

  • Prioritize writing readable code
  • Comment why not how
  • Comments can become outdated fast, and do more harm than good

 Question for you

What is your take on code comments? Do you use them, and if so when and why?


That's all for this rant, I hope I've made sense and removed some confusion around comments.


Cheers and have a great day!!

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