top of page
  • Writer's picturePratik Bhattacharya

You said what!? - Comments in Code

One of developers' most hotly contested topics of dissent is commenting their code. We have people from both sides of the camp, with one advocating the usage of comments and the other opposing it vehemently. Like most things in software development, there is no silver bullet to solve this never-ending debate, and like most things in Software development, it's completely relative. The usage of comments depends on your use cases, legal requirements and sometimes the complexity of the code.

There are 2 patterns we generally see in code - either too much comment (sometimes more than the code) or the other side of the spectrum - not a single comment in the code. In this blog, I will present some of my views and comments (did you see what I did there) about code comments. I will talk about common patterns, use cases of comments, and where to avoid them.




TL;DR 🤷‍♂️

The code is the only source of truth. Instead of cluttering your code with comments, aim at producing cleaner and more readable code.

  • Crisp comments that declare your intent and not tell a whole story

  • Add comments if it's needed for documentation

  • Comment only on the public interfaces and avoid commenting on internal logic, concrete implementations and private artefacts

  • Have comments for legal purposes, but avoid copy-pasting from other projects. Understand the correct legal requirements before adding copyright comments.

  • Have short-lived TODO comments, and prefer tracking tech debt and other todo items via backlog over comments


Who wrote this code?? 😡💢






Perhaps the most pertinent reason developers comment is to explain the code's internal behaviour. The strongest argument supporting this use case is the fact that new developers need to read and understand legacy code. Prima facie, this sounds pretty valid - new developers will join the team, current folks will move out, but the software will remain here for decades (at least, that's what we hope for when we are building systems). And there is software like core Microsoft Office applications (Word, Excel, etc.), the SABRE Airline Reservation System, core Linux modules and quite a few more, which has here before some of you were perhaps born. You may not know who had built these systems, but you still need new folks to maintain this code.


However, the golden rule when it comes to reading code is - 'THE CODE IS THE ONLY SOURCE OF TRUTH'. Documentations, comments, conventions - nothing explains the code better than the code. The problem with comments is that no one can vouch for the comment's veracity. It ultimately depends on the developer or developers who developed & coded; and how true they were to the comment. Generally, initially, when a comment is written, the comment truly reflects what the code does. But we need to remember that there might have been waves of upgrades, bug fixes, optimization, and revamp done on the same code for years. So even if we assume that the initial comment was a true statement, can we believe that every time someone touched the underlying code, the comments were updated. If the comments do not reflect the true nature of the code, making assumptions about the working of the code based on the comments can be dangerous. In such cases, no comment is better than bad and misleading comments.

My rule of thumb is that your code should be clean enough to explain itself. You can adopt various clean coding techniques like having descriptive naming conventions, manageable cyclomatic complexity, breaking complex parts into modular functions, etc., to write readable code. A practical litmus test is peer review - ask your peers to read your code and provide feedback about the understandability. When it comes to clean coding, my go-to relic is Uncle Bob's famous Clean Coder book.

Let's take an example of a small sub-routine

var status = (li) => {

if (li.length == li.filter(i => i.stock > 0))

return 1;

if (li.length == li.filter(i => i.stock == 0))

return 0;

return 2;

}

Can you completely understand what this method is doing at a first glance? Perhaps comments would have been helpful. Before we add comments, let's re-write the same sub-routine in a different way

const FULLFILLMENT_POSSIBLE = 1;

const FULLFILLMENT_NOT_POSSIBLE = 0;

const FULLFILLMENT_PARTIALLY_POSSIBLE = 2;

var getFullfillmentStatus = (lineitems) => {

const outOfStockItems =

lineItems.filter(lineItem => lineItem.stock <= 0);

if (outOfStockItems.length == 0)

return FULLFILLMENT_POSSIBLE;

if (lineitems.length == outOfStockItems.length)

return FULLFILLMENT_NOT_POSSIBLE;

return FULLFILLMENT_PARTIALLY_POSSIBLE;

}

Better now?




KISS (Keep It Short and Simple) 💋

The above code snippet brings another extreme practice - Don't comment bad code; re-write it. This can be an explosive statement, and sometimes there might be genuine cases where the underlying code is way too complicated. A genuine case of complex code is performance optimization. For example, let's say you are trying to record data about a 3D object in C#. Using a 3D array makes the code clean and development easy; however, from a performance perspective, a 1D array in C# is faster than 3D arrays. So for critical applications, you might end up using a 1D array.

Accessing a cell in a 3D array would be as simple as array[x][y][z]. However the same code in 1D array might be something like array[z + length * (y + length * x]. And when a new developer looks at the code, understanding the logic behind such calculation can be challenging. In such scenarios, comments can be helpful.

However, now we must be careful about what information is conveyed via the comments. Ask yourself, what's the most critical information you need to let the next person know about the code?

  1. Why are we using a 1D array instead of a 3D one?

  2. What is the translation logic behind indexing?

So try to explain the intent behind making a decision, and if that decision has caused any complication in the processing.

// 1D array has been used instead of a 3D array for improved performance

int [] array = Translate(Get3dObject());

// Each point on the 3D plane is translated to the 1D place, starting the from Z axis, followed by Y, followed by X.

int translatedIndex = z + length * (y + length * x);

return array[translatedIndex];

Do not try to go into too many details about each step. Developers reading the code are smart enough to derive the logic from the declared intent.

Be miser when allocating space for comments; try to use as less real-estate as possible to declare your intent. Be crisp, clear and logical.


There is a thing called Documentation 👴📰

I am an advocate of adding comments for documentation. However, there are a few guidelines I like to follow.

  • For strongly typed languages (C#, Java, TS) comment only on the public interface which clients will use

  • Avoid commenting on concrete implementation and private methods.

  • Comment API controllers, and use OpenAPI/Swagger conventions (or any other API documentation tools your organization might be using)

  • Only declare the intent behind the exposed interface. Do not explain the working - the core idea about interfaces is abstracting your clients from the internal working.

  • However, add enough depth to your comments to ensure that documentation generated from the comments is self-explanatory and easily usable by your clients without requiring much intervention.

  • Update the comments only if the changes will affect the client. E.g., if you are adding a new field in the response object. However, suppose it's an internal change (like you have decided to use NoSQL instead of SQL). In that case, you should not change the documentation (unless the new database requires new parameters, in which case client interfaces need to be updated).

The Lawyers ⚖

Some organization requires the usage of comments for legal purposes, like adding © statements. However, be careful and do not copy-paste such comments from other projects/codebases. Get in touch with the legal experts in your project and verify the type of License and copyright claims that you need to add to your code. E.g., if you are making your code open-sourced in GitHub, based on your organization's standards, you might be using MIT License or Apache License.


// TODO - I will do them ... one day 😜

My opinion on TODO comments is a little split. I agree with TODO comments, especially when you are adding something incomplete or are aware of optimization but don't have enough time to get to it. However, I have 2 rules :

  • Ensure they are short-lived. Do not have a TODO comment dangling in the codebase for more than 3 months. If a TODO comment has been lying in the production codebase for more than 3 months, then either the task is unimportant and can be ignored, or the task has low priority as per the current situation.

  • I prefer backlog to track tasks over TODO comments. If you think some optimization is needed in the current code or some tech debt is present, then it's better to track such items in the Product backlog rather than TODO comments. Tools like JIRA and Azure DevOps are good at tracking product backlog.

I prefer to keep TODO comments while a feature is actively developing. When the feature branch is pushed to the main branch for Production, I like removing all remaining TODO comments and adding them as backlog items.


That's it from me today; I would love to hear your comments (yes, I love puns) and feedback about how you comment your code.


References


1,569 views0 comments
bottom of page