When you think of a great developer, I’m sure someone who writes good comments often is not at the top of the list. However, writing good comments is one of the most important skills a developer can have. Good comments not only help you understand your code better, but they also make it easier for others to read and work with. In this blog post, we’ll look at why writing good comments makes you a great developer and some tips for improving your commenting style. Because if you are mindful in your commenting, it is an indication that you are mindful in your coding!
Comments Should Be Present
Well-written code comments are like a good road map. They provide clear direction and helpful information that can make working with code much easier. Good code comments can be incredibly useful, providing critical insights and details that might otherwise be easy to miss. Think of them as important signposts along the way that can save a developer hours of debugging.
Here is an example of something I came across recently that was not obvious. I was writing a CMake function to add unit tests using CTest. I was passing in a CMake string as my “TEST_COMMAND” variable. When I would call add_test with that variable as the value for the COMMAND option the test would fail to run properly, especially if the command took command line arguments! After spending some time digging I learned that the COMMAND option to add_test should be a CMake list rather than a string for the arguments to be passed properly.
I commented my CMakeLists.txt as such to ensure that was clear to the reader.
# TRICKY: Change the command string to a CMake list for use in add_test()
string(REPLACE " " ";" TEST_LIST ${TEST_COMMAND})
add_test(NAME ${TEST_NAME} COMMAND ${TEST_LIST})
Code language: CMake (cmake)
Without the “TRICKY” comment, a maintainer of this code may look at this and see potential for an optimization, removing the conversion, and then they would be searching for solutions to the same problem I had already solved.
Comments Should Use Proper Spelling, Casing, Grammar, and Full Sentences
Good code comments are spelled correctly. They are also properly cased. This attention to detail shows that the programmer cares about their work.
Take a look at the two examples of code below. Which one would you say is written by a mindful developer? Which one would you rather work to maintain?
// copute ac/a+c
double prodOverSum(int a, double c)
{// git the nmeratr for the rtn
double n = (double)a * c;
// get the denomination for the value
int d = a + (int)c;
/// comput and return the quotient
return n / (double)d;
}
Code language: C++ (cpp)
// Compute the product over sum for
// the provided values, a and c.
// (A * C)
// X = ---------
// (A + C)
double prodOverSum(int a, double c)
{
double prod = (double)a * c;
int sum = a + (int)c;
// Cast sum to a double to ensure
// the compiler does not promote prod
// to an integer and perform integer
// division
return prod / (double)sum;
}
Code language: C++ (cpp)
It’s clear that the programmer cares about their craft when they put so much effort into writing clear, readable comments. It would be almost impossible to maintain this level of detail by chance, which makes me believe it is intentional as opposed just being accidental! That gives me confidence that the code itself is well-written, properly tested, and ready for use.
When writing comments, it is important to use full sentences with proper grammar as well. This will help ensure that your comments are clear and easy to understand. Additionally, using proper grammar will help to give your comments a more professional appearance.
Comments Should Be Smartly Formatted
Comments are meant to convey a message about the surrounding code to the developer. Sometimes information is best conveyed in a particular format. So, when commenting your code, ensure that your comment is formatted in such a way that conveys your message as clearly and concisely as possible.
Code formatters can help and hinder this. If your comments require lots of horizontal scrolling to read, then consider breaking them into multiple lines or rewording to be more concise! However, sometimes a new line in the middle of your documentation is undesirable and you will need to instruct your formatter to leave it alone by wrapping with “control comments”.
For example, consider this method. If I was to line up all the columns in the table neatly, this would make for some very long lines of text. Most formatters would break these lines into multiple ones. Instead, make judicious use of white space to get the message across to the reader. If you have to use multiple lines, you decide where those line breaks are – don’t leave it up to your formatter!
void Quaternion2DCM(const double * const q, double * const dcm)
{
// Don't do this! Your formatter will either add new lines or ignore this
// if you add protection blocks around the table, making for really long
// lines that are harder to read.
// To compute the DCM given a quaternion, the following definition is used
// +-------------------------------------------------------------------------------------------+
// | (q4^2 + q1^2 - q2^2 - q3^2) 2*(q1q2 + q3q4) 2*(q1q3 - q2q4) |
// dcm = | 2*(q1q2 - q3q4) (q4^2 - q1^2 + q2^2 - q3^2) 2*(q2q3 - q1q4) |
// | 2*(q1q3 + q2q4) 2*(q2q3 − q1q4) (q4^2 - q1^2 - q2^2 + q3^2) |
// +-------------------------------------------------------------------------------------------+
// clang-format off
// Adapted from https://www.vectornav.com/resources/inertial-navigation-primer/math-fundamentals/math-attitudetran
// clang-format on
dcm[0] = q[3]*q[3] + q[0]*q[0] - q[1]*q[1] - q[2]*q[2];
dcm[1] = 2*(q[0]*q[1] + q[2]*q[3]);
...
dcm[7] = 2*(q[1]*q[2] - q[0]*q[3]);
dcm[8] = q[3]*q[3] - q[0]*q[0] - q[1]*q[1] + q[2]*q[2];
}
Code language: C++ (cpp)
void Quaternion2DCM(const double * const q, double * const dcm)
{
// Instead, you can do this - just simple white space, still very readable
// by the user and it fits on a single line!
// To compute the DCM given a quaternion, the following definition is used
// +-------------------------------------------------------------------+
// | (q4^2 + q1^2 - q2^2 - q3^2) 2*(q1q2 + q3q4) 2*(q1q3 - q2q4) |
// dcm = | 2*(q1q2 - q3q4) (q4^2 - q1^2 + q2^2 - q3^2) 2*(q2q3 - q1q4) |
// | 2*(q1q3 + q2q4) 2*(q2q3 − q1q4) (q4^2 - q1^2 - q2^2 + q3^2) |
// +-------------------------------------------------------------------+
// Adapted from https://www.vectornav.com/resources/inertial-navigation-primer/math-fundamentals/math-attitudetran
dcm[0] = q[3]*q[3] + q[0]*q[0] - q[1]*q[1] - q[2]*q[2];
dcm[1] = 2*(q[0]*q[1] + q[2]*q[3]);
...
dcm[7] = 2*(q[1]*q[2] - q[0]*q[3]);
dcm[8] = q[3]*q[3] - q[0]*q[0] - q[1]*q[1] + q[2]*q[2];
}
Code language: C++ (cpp)
How Much Should I Comment?
Good code will be somewhat self-documenting, but there is always a limit. For example, the method below is so obvious I don’t really need to comment on it, do I?
int sum(const int a, const int b)
{
return a + b;
}
Code language: C++ (cpp)
However, for something more involved, comments can clarify a lot of things for the developer and can link them to more information, as in the example of the Quaternion2DCM method described above.
So, then, how do you define what is obvious? For me, I think in terms of my average user and/or maintainer. What sort of things do I expect them to understand? What about more junior software engineers who may need to work in this code? Basic math and logic knowledge seems okay. Syntax is a given; even more advanced syntax, such as lambdas or function pointers, I would expect them to be able to read. However, anything beyond that typically indicates the need for a detailed comment that explains things.
It also helps me to think in terms of what will help me understand this design decision tomorrow, or 6 months from now, or even a year from now. Maybe it is obvious to me now what that this conditional with multiple clauses means and why it is this way in the design, but I’ll likely forget tomorrow and want to refactor.
Comments In Your IDE
To make working with comments easier, look for ways to get your IDE to help you! I use VS Code for nearly all my coding right now and I found the extension Better Comments to be extremely helpful.
With this plugin I can add additional formatting and mark comments specifically. For example, in my code I tend to leave myself reminders using TODO and will often prioritize those TODO comments using regular TODO and prefixing with ‘*’ and ‘!’.
// ! TODO: This is an important TODO that needs to be taken care of immediately
// * TODO: This is an important TODO that should be taken care of soon
// TODO: This is a TODO that should be taken care of eventually
Code language: C++ (cpp)
With this plugin my comments are color-coded for me, making it easy to see what needs to be done first.
In the end, your code is the reflection of you, so it only makes sense that your commenting reflects how much care and attention to detail there really is in what’s being written. If poor commenting sends a message on its own then people will be able to tell if they need more time before investing any kind of faith into your code—or even worse, they’ll just move onto another potentially better implementation!
What do you think? What makes a good comment in your book? Let us know in the comments below!
Comments