DEV Community

Cover image for My take on commenting code - Explain why, not how
Keff
Keff

Posted on

My take on commenting code - Explain why, not how

// 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!!

Discussion (14)

Collapse
katafrakt profile image
Paweł Świątkowski • Edited on

For me, the most important reason to write the comments is when I know that the code in question is counterintuitive. For example, a code that I wrote yesterday:

total = 0
products.each { |p| total += p.price * p.quantity }
total
Enter fullscreen mode Exit fullscreen mode

This code screams USE MAP DUDE:

products.map { |p| p.price * p.quantity }.sum
Enter fullscreen mode Exit fullscreen mode

Well, as it happens, products is not an array, but an object from an external library, that implements each but doesn't implement map (don't ask). I know that me in 4 months and any other person might not remember that and will sigh and try to refactor this code, only to fail. That's why I'd put a comment explaining why this code looks this way.

Collapse
nombrekeff profile image
Keff Author • Edited on

Fantastic reason, thanks for sharing!

And a really nice point, adding comments when refactoring, renaming or creating a new method is not possible, for example for 3rd party libraries, as you mentioned! This would fall into the "comment why not how" idea, as you can't control the how in this case.

Collapse
auroratide profile image
Timothy Foster

Code comments are intended to add more context to your codebase, in case the code itself is not enough

Completely agree! Or as I like to put it, comments tell you what code can't tell you.

Collapse
nombrekeff profile image
Keff Author

Nice way to put it, might use it in the future ;)

Collapse
gudata profile image
gudata

Here is one more usage of the comments in order this article to be complete.

When I want to write something with multiple steps I like to draft them as

# Do first
# for each item
# do something else
# Do final thing
Enter fullscreen mode Exit fullscreen mode

So then I implement the logic bellow the comments

first()
for each item in items:
  something_else()
final()
Enter fullscreen mode Exit fullscreen mode
Collapse
nombrekeff profile image
Keff Author

Fantastic addition, I also do this, it's a simple way to map out your ideas. I either do it with comments or using a markdown file, I prefer using markdown as I can then keep a log of what my thought process was at the time!

Collapse
aarone4 profile image
Aaron Reese • Edited on

My main language is SQL and comments are vital, especially where code is there to explicitly get around a data quality issue that may be temporary
Not stated in the article but PLEASE use /+block comments+/ rather than //line comments. (Use stars not plusses: Dev editor removes stars!)
In the event that some repo or copy-paste removes line breaks block comments won't break or change the behaviour of code.

Collapse
nombrekeff profile image
Keff Author

Good points, I'll take note on them!! I see why comments are essential when writing SQL.

I've never thought about the issues of using line comments, have you ever encountered an issue using them? Or is it a rare scenario?

Collapse
simeg profile image
Simon Egersand 🎈

I've heard reasoning for both sides (comment a lot vs. never). I agree with you though. I try my best to avoid comments but sometimes it's warranted.

My decision making is something like "will myself or someone else be confused by this code (that I can't, for some reason, make cleaner) in a month? Better add a comment".

As I've gotten more experienced with programming, the less comments I write. But the more docs (Java docs for example) I write.

Thanks for sharing! Good stuff.

Collapse
nombrekeff profile image
Keff Author

Thanks for reading!! I agree with you as well, there's times that it's difficult to make clean/understandable code with the time we have to work on it. So adding a comment can be a good solution!

Collapse
andrewbaisden profile image
Andrew Baisden

Without commenting we would probably get lost in an unfamiliar codebase.

Collapse
nombrekeff profile image
Keff Author

Interesting, in which way would you say they help you navigate codebases? Have you ever felt the opposite way in any codebase?

Would you mind sharing some of these comments so we can better understand what you mean?

Collapse
andrewbaisden profile image
Andrew Baisden

Sometimes it's not always obvious what a block of code is doing. Every developer has their own way of setting up a project architecture. So commenting can help to get someone up to speed if onboarding them with another developers help is not an option.

Constructive comments are always welcome. The VS Code extension Better Comments is a good example of comments done well.

Thread Thread
nombrekeff profile image
Keff Author

Ohh okay, I see where you're going. I have to agree. This is in part what I was referring with explaining why you do something and explaining things code can't explain. Context on how a project is architected and why things are done in the way they're done. I also welcome these kinds of comments, and write them myself. I have no problem with them. My issue is mainly the comments explaining obvious or convoluted code, that could be better of just by refactoring and naming stuff correctly

For me these types of comments fall just in the line between code comments and doc comments.

Cheers, and thanks for the addition!