On Commenting Code
Code comments are a help line for your PR reviewer, your coworkers, and your future self that might just help them out on their darkest day. It can feel like a chore. Comments can even detract from your work when done poorly. But when done well, comments can be be immensely helpful.
Self Documenting Code - The Unobtainable Goal
In an ideal world there would be no need to comment code. We wouldn't have to spend time writing comments, rewriting comments, reading comments, or scrolling past comments to find the next block of code. Variables, constants, functions, and classes would be named so that their utility is immediately clear to any reader. Inline values would only be used when their use was unambiguous e.g. the two in let circumference = 2 * PI * radius;
. Algorithms would be clear from the structure of code within files and features would be obvious from the files that comprise our projects.
Unfortunately, this is not the world we live in. Sometimes a dependency simplifies our code but the function interface is full of types and methods named in ways that are foreign to us. Sometimes a value seemingly comes out of nowhere e.g. 0x5F3759DF or 0xE85250D6. Sometimes we are defining an interface for use by programmers who don't share our understanding or conventions. For these reasons and more, no matter how well we write our code, chances are we need to add some explanation.
Writing Good Comments
What makes a comment good or bad? In my experience good comments speak to their audience, and don't obscure code, and explain code clearly and concisely.
A Comment's Audience
Comments take many forms because comments can solve many problems. This is just another way of saying comments inform many audiences:
- Your current coworker e.g. a peer reviewer
- Your future coworker
- An outsider hoping to integrate with your code
Understanding who you are writing for will help you write better comments. A comment for a current coworker can be written assuming that the coworker understands the coding standards and patterns used in the project. For this audience, you will want to call out when you have deviated from or appear to have deviated from those standards and patterns.
# This is weird perl syntax. `selectcol_arrayref`` essentially returns a pointer # to an array of strings. Wrapping it in @{...} allows us to use the array directly @fields = @{$DBRW->selectcol_arrayref($query, {}, $key)};
New team members can be expected to have some familiarity with programming but not the product as a whole. For this audience, you will want to explain how a file fits into the bigger picture.
<?php /** * This file provides the auto-extraction/execution logic for our * redistributables. This script is NOT meant to be executed independently. * Instead, this file is an input to the build process and serves as the * preamble for the self-extracting .php script which is created. */
An outsider can be expected to have an understanding of programming but not the patterns used or the assumptions made in a project. You will want to explain to them the project's assumptions and at interface boundaries the expectations for code integrating with the project e.g. memory life cycles.
The UX of Comments
The reader we address in our comments is a special user of our code. We are at our best when we consider the experience of our users, even those special users who have a use for our code uncompiled and uninterpreted. By showing consideration for their focus and usage patterns we make our code more maintainable.
Newspapers placed headlines and eye catching images "above the fold" to capture our eyes in the hopes that we'd buy the paper to keep reading. Similarly, if we place our most important comment at the top of a file where editors will open the file by default, we capture our readers attention and make the best use of their time by hitting them with the big idea upfront. Therefore you should always include the big ideas for your code in a comment at the beginning of a file or just before the top level block e.g. the class defined in the file.
Conversely, some comments simply repeat the name of a variable, constant, function, or class.
/** * A specific field to be filled out. */ class FormField { … /** * Set the unique ID of the Form associated with the FormField. * * @param int $formId * @return FormField */ public function setFormId(int $formId): FormField {
Because we try to name variables, constants, functions, and classes to be descriptive, these comments clutter code without communicating any ideas. Comments which describe the history of code
# Copyright SOME EMPLOYER. USA. All rights reserved. # # Description # # rev: AUTHOR 110726 New rev # AUTHOR 150515 Fixed: It is not an "error" if while using a bucket # widget a user tries to a group without users. # AUTHOR 190627 Fixed: TR-332 Customer users see customer support users in # user lists
/** * YYYY-MM-DD - developer@company.tld * Previously we were using "NOW()" as the value to test against, but this will * fail because NOW() will return the time truncated to the second while our * expectation value includes the microsecond */also clutter your code while providing minimal information; information your version control software is specially designed to track for you. Comments like these distract from the code making it harder to read and obscure more important comments break our reader's focus and should therefore be removed.
Code Comments as Technical Writing
It probably shouldn't be a surprise that commenting code is a form of technical writing. Writing code after all is a highly technical art. While the compiler or interpreter is a final arbiter of whether code works, humans, including your coworkers and your future self are going to decide whether code is artful. Fortunately, as human beings we have some commonality. We tend to like simple. We tend to like the big idea up front. We tend to feel excluded by jargon. We tend to like patterns. When it comes to writing:
- We want to read short sentences
- We want paragraphs to lead with topic sentences
- We want to be introduced to strange words before they are used
- We want parallel structure in lists
We can write more inclusive and accessible code comments if we:
- Use terms consistently.
- Avoid ambiguous pronouns.
- Prefer active voice to passive voice.
- Pick specific verbs over vague ones.
- Focus each sentence on a single idea.
- Convert some long sentences to lists.
- Eliminate unneeded words.
- Use a numbered list when ordering is important and a bulleted list when ordering is irrelevant.
- Keep list items parallel.
- Start numbered list items with imperative words.
- Introduce lists and tables appropriately.
Source: https://developers.google.com/tech-writing/one/summary
How to Handle Bad Comments
Just as a world without a need for commenting code is an unobtainable goal, so too is a world without bad comments. So I figured I ought to finish with a few words on what to do when faced with a codebase of poorly commented code. First
Don't PanicThere is no need to write a regular expression to delete all of the comments. Some of the comments may have a nugget of truth or relevance so deleting them may make the situation worse. Instead I suggest taking an iterative approach. Make targeted changes that individually make your code more understandable and readable. Focus first on the comments which are wrong or misleading. Improve readability when it is a quick and easy change. Above all iterate.