Comments are useful. You just need to learn when to use them

Search for a command to run...

Insightful information Rodrigo 👍🏻👍🏻👍🏻
Great Article!
Awesome article, my thought before writing a comment is always to write the "WHY" of the function with minimal "WHAT" it does.
"Occasionally you may find outdated comments in the code that can create confusion."
Why is that happening? Because one might update the code and not the comments?
Nevertheless, amazing article. Well done! 👍
Excellent article, well thought-out! I'd like to stress a lot about justifying choices or explaining why there must be a workaround by providing a Stack Overflow thread of a GitHub issue. This saved me countless times from trying to mess up something believing that I could make it better or fix it.
You touched on an important point.
Sometimes, in our need to leave the code clean or optimal, we immediately change the original code for a better version, but sometimes, there is a reason behind that code and out of ignorance and not having a proper context, we end up changing it anyway.
Thank you, I'm glad you liked the article.
We’ve all seen it: AWS keys sitting in GitHub Workflows. They might feel convenient at first, but if they ever leak, it’s a nightmare—especially when those keys have wide IAM permissions. Rotating them every 90 days means generating new keys, updatin...

Combining Jest and Jasmine: Seamless Integration and Coverage Report Merging

Here’s a quick how-to guide for running a large language model (LLM) locally using three tools: Ollama, Ngrok, and Cursor IDE. This setup is perfect if you want to test AI features without relying on OpenAI’s cloud, or if you're just nerding out and ...

Before telling you how to create an outstanding portfolio, I want to tell you my personal story of how I got my first job eight years ago. How did I get my first job I was a third-year college student about to start my vacations, the only moment when...

What's the difference?

Perhaps you may have heard some of the following statements:
The thing is that writing comments aren't bad at all if you know in which cases they can help us and on which others they are a complete waste of time.
Code should be expressive and intention-revealing. Needing comments to explain the code means the code doesn't describe itself well enough.
Our code is read far more times than is written, so we should aim to make it as easier to read as we can.
Sometimes it's clear when a comment is redundant.
// Calculate the square root of the sum of two numbers
const result = Math.sqrt(a + b);
// Timeout of 30 seconds
const timeout= 30000;
But other times, knowing if the use of comments is a good or bad idea, is confusing.
Consider the following example:
/*
* Calculate the total amount to pay for a pizza going through each
* item in the order and obtain the cost of each ingredient of the
* price object searching by section and ingredient name to then add
* each subtotal and return the total to pay
*
* @param {object} o: pizza order
* @param {object} p: ingredients prices
* @return {number} total: total price to pay for the order
*/
function total(o, p) {
let total = 0;
Object.keys(o).forEach((key) => {
if (key !== 'ingredients') {
total += p[key][o[key]];
} else {
o.ingredients.forEach((value) => {
total += p.ingredients[value];
});
}
});
return total;
}
In the above code, we used JSDocs, which is a fancy way to create documentation automatically by reading the comments and special tags like @ param or @ return that specify the parameters and the value returned by each function. Although JSDocs has justified use, when used for the sole purpose of describing what the code does, it becomes useless.
We can refactor the previous example using descriptive and meaningful variable names, moving some logic to a smaller function so that its name explains what the function does. After that, we will soon realize that all such comments are unnecessary.
function calculatePriceToPay(pizzaOrder, tableOfPrices) {
let totalPrice = 0;
Object
.entries(pizzaOrder)
.forEach(([section, item]) => {
totalPrice += getItemPrice(section, item, tableOfPrices);
});
return totalPrice;
}
function getItemPrice(section, item, tableOfPrices) {
let price = 0;
if (Array.isArray(item)) {
price = item.reduce((accumulator, subItem) => {
return accumulator += tableOfPrices[section][subItem];
}, 0);
} else {
price = tableOfPrices[section][item];
}
return price;
}
The only reason to hesitate before removing those comments is if the JSDocs is actually been used to create documentation, if not, or if they were another type of comments we could remove them immediately.
See?. The calculatePriceToPay function is much simple to read after the refactoring even without the comments.
When we write code with intention revealing and easy to understand, every previous comment whose sole purpose was to explain the code, lose completely its value, and therefore we can remove it
Whenever you find comments used to explain what the code is doing I invite you to question if they are really necessary because in the majority of cases those comments aren't needed, and can be deleted.
We should understand what the code is doing after reading it line by line and not by reading a description.
Another reason is that code is alive, it changes more frequently than comments and even documentation, so it's more likely to see comments become obsolete sooner than you think.
As in everything, there are exceptions. There is one case in which we can use comments to describe the code; If we are building a really complex algorithm or performing complex operations, in non-trivial domains like statistics, physics, chemistry, healthcare. In those situations, we can give additional context and reinforce the self-described code through the use of comments.
Let's see an example:
import math
EARTH_RADIUS_KM = 6371
def get_distance_km(src_lat, src_lng, dest_lat, dest_lng):
"""
Calculate the linear distance between two points in the earth using
the Haversine Formula
The points are GPS coordinates with a latitude and longitude
represented as floats numbers
"""
DEGREES_TO_RADIANS = math.pi / 180.0
# Convert latitude and longitude to
# spherical coordinates in radians
phi_src = (90.0 - src_lat) * DEGREES_TO_RADIANS
phi_dest = (90.0 - dest_lat) * DEGREES_TO_RADIANS
theta_src = src_lng * DEGREES_TO_RADIANS
theta_dest = dest_lng * DEGREES_TO_RADIANS
# Compute spherical distance from spherical coordinates.
cos = (math.sin(phi_src) * math.sin(phi_dest) * math.cos(theta_src - theta_dest) +
math.cos(phi_src) * math.cos(phi_dest))
arc = math.acos(cos)
distance_in_km = arc * EARTH_RADIUS_KM
return distance
As you can see above, even with a clean code, it's difficult, near to impossible to understand what the code does. Why is that?, It's because it requires domain-specific knowledge. The variable names represent mathematical symbols and formulas but none of them give us context to understand what those formulas are needed, the use of comments, in this case, guides us through the steps and delivers us additional context.
With the use of those comments, we can quickly search on google for "Haversine function" and "spherical coordinates" to get the missing information.
Comments are a great tool to explain things that cannot be explained through the code.
They are good for express the reasons behind our decisions and provide additional context.
// Needed to handle Webpack and faux modules
// See https://github.com/fastify/fastify/issues/2356
// and https://github.com/fastify/fastify/discussions/2907.
// Typescript quirk - libraries exported with `export = ` need to be imported using `require()`.
// See: https://github.com/microsoft/TypeScript/blob/master/doc/spec.md#1135-export-assignments
import chaiShallowDeepEqual = require('chai-shallow-deep-equal');
// Override timezone formatting for MSSQL
// link: https://stackoverflow.com/questions/47056395/how-to-pass-a-datetime-from-nodejs-sequelize-to-mssql
// Some errors contain not only line numbers in stack traces
// e.g. SyntaxErrors can contain snippets of code, and we don't
// want to trim those, because they may have pointers to the column/character
// which will get misaligned.
const trimPaths = (string: string) =>
string.match(STACK_PATH_REGEXP) ? trim(string) : string;
/**
* Initialize a new `View` with the given `name`.
*
* Options:
*
* - `defaultEngine` the default template engine name
* - `engines` template engine require() cache
* - `root` root path for view lookup
*
* @param {string} name
* @param {object} options
* @public
*/
// This file is autogenerated by build/build-validation.js, do not edit
/**
* This module contains code that will be migrated into
* its own service
* DO NOT ADD MORE CODE INTO THIS MODULE
* see epic: https://jira.example.com/browse/PM-32145
**/
Comments can lie, that is a fact that can create confusion because, unlike code that keeps evolving, comments are rarely updated because it's not our priority as developers
In addition to redundant comments, we should avoid those that are implicitly or explicitly time-limited.
For example, the famous TODO or FIXME comments are used to let everyone know that there is a debt in the code that we must pay in the future, but the future could never come, and no one will review the code when the team needs to prioritize work. Instead of those comments, create a task in your task manager and label it "Technical Debt" to track how much debt the project generates and how much is paid in each iteration.
Comments are just another tool to solve a specific problem. The problem here is the lack of understanding after reading our code.
They aren't the bad of the movie, but they can become a waste of text so it's important to know when they are beneficial and when using them is nonsense.
As a general rule, write comments when you need to provide additional information that cannot be expressed through clean code.
If you like the article and want to support me to write more content like this