• Stefan Pauwels

  • Software Engineer

There is a tendency in the software world to write less and less comments, mostly because developers don’t have a lot of time. Instead of writing down comments, developers may choose to spend their efforts fixing bugs and completing new features.

A second possibility could be that developers, with the help of better framework support and new language features, can now write self-explanatory code. This is the kind of code that is so clear that adding a comment would only duplicate what has already been written down.

These challenges make the writing of comments a thing of the past, as adding extra documentation usually duplicates what we have already written. Nonetheless, there are still some core situations in which a comment has added value.

Trivial example

Comments should explain what the goal of a piece of code is and why a piece of code is written. However, it should never explain how it solves the issue at hand. An example of a clear comment is the following:

/**
 * Sort the parties on created date ASC and then on name case
 * insensitive ASC. The case is important because some names start with a lowercase character. For example “bPost”:
 * Using natural sorting will move “bPost” to the end behind the last item while it should be behind “Beckaert”
 */
private List<Party> sortPartiesOnCreatedDateAndName( List<Party> parties)

The name sortPartiesOnCreatedDateAndName already tells us that the parties will be sorted by date and name, but it fails to explain why the names were sorted case-insensitive. The bPost example is useful here because it clearly explains why case-insensitive sorting is so important in this context.

Now we will show 3 examples in which it makes perfect sense to write a comment. As in: Your technical lead will know where to find you if you don’t write a comment in this context.

1. Deprecating a function

Deprecated is used to warn the developer of a function that should no longer be used due to removal in an upcoming version. Instead, the developer should always use another improved function. The usage of a comment in this situation is highly beneficial and recommended. Without a deprecation comment to redirect the developer to the new functionality, nobody would know what is going on. The developer will waste precious time searching for the new improved function in the documentation. Sadly, time is a commodity that developers do not have. Take the following example:

/**
  * Get The amount of years from this Date.
  *
  * @deprecated As of JDK version 1.1, replaced by
  * Calendar.get(Calendar.YEAR) - 1900.
  */
@Deprecated
public int getYears()

This example comes from the java.util.Date class. The comment clearly states that the use of getYears has been deprecated since JDK version 1.1. This information urges developers to use the Calendar class instead. In short, a deprecation comment should clearly state in which version the piece of code has been deprecated, and what to use instead.

2. Third party workaround

At any given time we developers are using a lot of external libraries in our projects. If one of those libraries has a bug, we can report it and hopefully they will fix it soon. However, code must still be written to work around this bug in our project.

It's important to document what the reason was to write a workaround, because developers will frown upon a piece of code that they do not understand. Their first reaction might be “I need to remove this part”.

To prevent that from happening, it is recommended to write down which external library caused the issue and how this issue was solved. Additionally, if there is an issue ticket, include the ticket number of the third party bug tracker.

private Dimension createTableSize(long width) {
// Width is always positive. The call to abs() is a workaround
// for a bug in the 1.1.6 JIT on Windows.
long tmp = Math.abs(width);
}

At one point, the width parameter mentioned above could have apparently been a negative number in a specific case (i.e. the case of the JIT 1.1.6., on Windows). The comment explains how this issue was fixed by ensuring that the width is always converted to a positive number by dropping the sign. So this line wouldn’t make much sense without the accompanying comment.

/**
 * Unfortunate naming because of the property expression. By
 * using an underscore character we can tell Spring to use the
 * correct property Subscription.SubscriptionId in the query.
 http://stackoverflow.com/questions/33438483/spring-data-jpa-query-manytomany
 */
@SuppressWarnings"InstanceMethodNamingConvention" )
Collection<Unit> findDistinctBySubscriptions_SubscriptionIdOrderByName( String id )

In the example above, we use a comment to explain why we are using an underscore in the function name. Even though this is not really good practice in the Java community, we are forced to use it here because that is how the Spring Data method name convention works. The StackOverflow URL is included to allow further reading on the topic.

3. External references

Many problems that developers face have already been asked, blogged and/or written about by someone else. When you find the solution online, it's important to document at least 2 things:

  1. A condensed summary of the solution that you have used.
  2. A link to the website where you have found the solution.

At this point you may ask, why not just include the URL? After all, it already contains all the information you need. However, it is very likely that your code will outlive the link and, even worse, if the link dies, you may have no information at all. That's why it’s good practice to include the explanation above the URL, like so:

// This converts the given hex color like "#456412" to a RGB value.
// The RGB value is a string that is in the following format: "r,g,b"
// http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#answer-5624139
function hexToRgb(hex)

As shown above, a small explanation of what the function does and what the input and output are, is placed in the comment. The comment is then followed by the URL, which takes you to StackOverflow from where the hexToRgb function was originally copied from.

In other words, linking to the external reference gives you a wealth of information, and a topic for discussion as to why this is a good solution. And when the link dies, you still have all the relevant information above the URL.

Conclusion

In this blogpost we have shown you some examples of situations in which comments are still necessary. These situations are deprecated code, working around an external bug and linking to an external reference in your code. Remember, each situation is unique and the above points are just guidelines.

It happens regularly that developers may update a code fragment, but forget to update the accompanying comment. However, comments that are not in sync with the code are confusing. One solution to this problem is to add a point to your code review process to check for code and comment mismatches. For more information about project documentation, please see our blog post Defining an Efficient Documentation Structure.

We acknowledge that it is always better to write clean code than to write a comment that explains bad code. You should always try to refactor, and using meaningful variable and function names will go a long way in improving the understandability of your code.

Though there is a fine line between writing too few comments and too many, the worst you can do is to write no comments at all. Hopefully, these three tips will make it easier to determine when to write a comment.