There are two main stances towards commenting:
- Comments are an indicator for code that is not self-explanatory.
- Comments are the most explicit way of communicating the programmer’s intend.
I follow the second philosophy. Even fully self-explanatory code can benefit from good comments, because it can remove ambiguity by explicitly indicating intend. Too often code seems self-explanatory and yet it is not and the reader has a different mental model than the author.
General guidelines
When writing comments there are some general guidelines to follow for writing good comments that improve the readability and maintainability of the commented code.
Form
The formal structure of the code should be coherent within a code base. If there are standards for your language or your project they should be honoured. This is especially true for all head comments for classes and methods; even more in dynamically typed languages that don’t enforce signatures, like JavaScript and PHP.
Good examples for standardised head comments would be JavaDoc, JSDoc or PhpDoc.
JavaDoc
1 2 3 4 5 6 | /**
* Some fancy function that does impressive stuff.
* @param foo a totally generic input parameter
* @param bar another even more generic input parameter
* @return an object containing all the impressive stuff done to foo and bar!
*/ |
JSDoc
1 2 3 4 5 6 | /**
* Some fancy function that does impressive stuff.
* @param {number} foo a totally generic input parameter
* @param {string} bar another even more generic input parameter
* @return {FooBar} an object containing all the impressive stuff done to foo and bar!
*/ |
PhpDoc
1 2 3 4 5 6 7 8 | /**
* Some fancy function that does impressive stuff.
*
* @param int $foo a totally generic input parameter
* @param string $bar another even more generic input parameter
*
* @return FooBar an object containing all the impressive stuff done to foo and bar!
*/ |
C#Doc
1 2 3 4 5 6 7 8 | /// <summary> /// Some fancy function that does impressive stuff. /// </summary> /// <param name="foo">A totally generic input parameter.</param> /// <param name="bar">Another even more generic input parameter.</param> /// <returns> /// An object containing all the impressive stuff done to foo and bar! /// </returns> |
But not only the head comments should be well-structured. Inline comments profit from good form as well.
Single line comments should be on a single line. They should not be at the end of a statement-line and not happening as a big block of comment (unless your language discourages multi-line notation).
What many people do not see at write time and regret afterwards is abbreviated or grammatically shortened commenting. Abbreviations could get forgotten and lose their meaning over the years. “UAuth” could mean “user authentication” or “unit authorisation”, depending on culture and context.
And incomplete grammar can lead to ambiguity. // Resize
next to a print margin operation is less descriptive than // Uses translated input multiplier to resize the print margins.
Always keep in mind that a different programmer, you currently do not know, must be able to work with your code with a minimal amount of (ideally without) onboarding time and tutoring. Always keep in mind: That code you currently do not know could be you in 6-18 months! If you constantly switch projects or even focus on different parts of a big project over time and keep growing, like every driven developer should be, you will not remember those small shortcuts and insiders in a year or two, or even a couple of months from now.
Function
Code comments can have various functions. The most obvious, and most likely the biggest reason for the beating that comments as a concept need to take, is explaining badly written code.
If something is totally unintelligible without a comment chances are, that your code needs some refactoring. We are not here to excuse that!
The most important reason for proper commenting in dynamic languages is auto-complete, debugging, static analysis and jumping through the code in your IDE. This can be achieved by header docs like in the examples above. Those comments tell your IDE, what is what, how it is called and what type you expect it to have.
In statically typed languages this is not necessary, but increases clarity. The header comments are a means to give context or point out meaning behind the obvious.
Then there is the semi-sarcastic comment, noting out a notorious passage or a piece of code that breaks rules on purpose, because they make no sense at that place.
// Dear maintainer: // // Once you are done trying to 'optimize' this routine, // and have realized what a terrible mistake that was, // please increment the following counter as a warning // to the next guy: // // total_hours_wasted_here = 42
This seems to appear especially often if interfacing with weird third-party code, you have no control over.
Other valid types of comments I see often are //FIXME
, //TODO
and Examples; I like to put example JSON or XML in methods that are meant to consume external HTTP APIs.
A type of comment that is on the edge of what’s widely accepted are comments indicating a new concept or passage of a method. At first this type seems totally legit, but when looking closer this type of comment often actually is a code smell-indicator: if you need to point out something new starting off, you probably should shard that new thing out as a separate method/function. If that seems impossible, because for example you use lots of variables you probably should over think the method as a whole.
Importance in dynamically typed languages
Everyone who has worked on a sizable and dated php or JavaScript code base knows this issue:
Some code behaves weird, you start diving into the code and at some point you reach a variable where you have no clue, what the type is or where it initially got initialized.
This problem generally only exists in dynamically typed languages, because the IDE has no idea what type to expect, if the comments don’t tell it.
So dynamically typed languages benefit from the structured comments, because it is the main tool of making a big tangled ball of spaghetti a solid, structured and legible code base.
Most dynamic languages with structured commenting systems allow type definitions everywhere, inline and on methods heads.
Self-explanatory code vs. fully commented code
As you probably noticed by now there are comments that occasionally could be seen as a red flag for code smells. That is true.
BUT, and that is all caps on purpose, what is even worse in my eyes are totally uncommented bodies of code, that seem clear at first sight and when reading them without knowing the context all sorts of misunderstandings and ambiguities happen, because the original author did not see some unclear language or did not know that certain phrases or abbreviations are not common knowledge.
This is why I prefer full commenting. If the comment and the code tell the same story everything is good. If both are clear and precise that’s awesome. If one tells one story and the other a different one, that is a red flag. This is the point where the code needs to be read very thoroughly and probably it’s a good idea to track down the author, if it’s not been your past self.
Tools & helpers
There are some little tools and helpers for good commenting.
GhostDoc
GhostDoc is a VisualStudio plugin, that automatically generates header comments for C#-Code. This means, it tries to derive a nice spelled out description for the a commented method or its parameters and explicitly marks things it is not clear about. So for most things that are named well you only need to click the code entity and press ctrl-shift-d for a decent comment with all necessary fields filled out; only the return usually has to be filled by hand. Also for Properties and fields it generates standard-complient comments like Gets or sets a value indicating whether the user has been authenticated.
. Usually you still have to lay hand on the comments, but it is definitely a good point to start from.
Visual Studio Snippets
For repetitive comments that GhostDoc cannot deliver I created Visual Studio snippets. Snippets are pieces of code that can be pasted via a shortcut (my VS opens the dialogue for snippet insertion via ctrl-k+x followed by arrow down). An example you might know from my other posts’ examples is the file header comment block aka copyright-block:
1 2 3 4 | // <copyright file="SomeFile.cs" company="Marc A. Modrow"> // Copyright (c) 2018 All Rights Reserved // <author>Marc A. Modrow</author> // </copyright> |
I have a snippet for this, that includes all of this, except the file name, which usually can be copied from the class name.
You can include new snippets by putting them into a file somewhere on your drive and include the containing folder via the snippet manager (ctrl-k+b). Those files have the extension .snippet
.
For detailed explanation of the different tags, structure and placeholders you can have a look at the official documentation.