How bad comments are born in your code

Many programmers mention their support for “good” comments in the code. A significant percentage of all developers think the quality of the comments is one of the traits that separate good experienced programmers from the rest. But the cruel reality is lots of code out there is not commented at all or, even worse, it is commented but the comments are so bad they make understanding the code harder.

In recent posts Dan Dyer and Jeff Attwood took somehow different positions regarding what good comments are and if we need comments at all. I tend to agree that sometimes too much commenting is bad. But this is because the useful information in those comments is spread thin. I don’t think going to the extreme and having comments replaced with just relevant class/method naming is a good idea because you cannot express full intent in a class/method name. This is actually why you have to write some code inside the class or the method, isn’t it? I actually see a lot of value in approaching comments the way Avi Pilosof describes business commenting.

If code comments are so important then why so much code is poorly commented? To answer the question let’s see first why we comment our code in the first place:

  1. Make it easier for somebody else to understand what the code does
  2. Make it easier for the author to remember what his intentions were
  3. Explain the flow
  4. Explain or at least name the algorithms and the choice of algorithms
  5. Warn of unexpected behavior and side effects
  6. Help the maintenance programmer avoid creating problems when the code is fixed, modified or extended
  7. Explain the assumptions at the time of writing
  8. Explain the constraints at the time of writing
  9. Describe the requirements at the time of writing
  10. Explain the implementation decisions (why the code is designed/structured/written that way)
  11. Explain why the code was modified/fixed and mention the bug ID (at maintenance)
  12. Describe how the code was modified/fixed and what the desired effects are (at maintenance)

To summarize with only one word the reason for commenting code is maintenance!

At this moment we can postulate that comments addressing these issues are good comments. So characteristics of bad comments are, by contrast:

  1. Lack of comments
  2. Unmaintained comments – wrong comments misleading the reader
  3. Useless and bloated comments – stating the obvious and diluting the information
  4. Comments that focus only on how things are done not on why they are done that way

How bad comments are produced:

  1. People don’t want to write comments for reasons ranging from laziness to philosophy and perceived job security. Some programmers think their code is very clear while others don’t think at all about the future of that code. But the code is clear only in their minds since they already know all the requirements and the constraints.
  2. People don’t know how to write good comments. Some programmers really want to have comments but they don’t know what information to put there or, pressured by time constraints they simulate comments just to pass a code review. This is how bloated comments that explain nothing are born.
  3. People focus on how the code works instead of why the specific solution was picked. The developer wants to write comments, finds the time to write them but focuses on the methods of doing things and completely forgets to provide a glimpse into the reasoning behind the technical decisions.
  4. People forget to update/maintain comments. It happens more often than not – the code is changed but the comments are left around describing now gone functionality. This happens when new features are added, when the code is re-factored and when bugs are fixed.
  5. No incentive for writing good comments. I never heard somebody (a manager?) praising a programmer for the quality of the comments in the code. This also applies to code created by contractors or to code outsourced to another company.
  6. There is no interest in commenting the code properly. Sometimes the developer will never be the one to maintain the code. This quickly translates in lack of comments or in useless comments. Examples are developers in organizations that separate completely the development and the maintenance activities. Also contractors sometimes tend to have the same view on comments and as a result companies who outsource code development don’t get maintainable code if they don’t enforce some quality standards through reviews. And usually this is what happens since the review process is very time consuming. Contractors might be interested in doing the job as fast as possible but not in spending extra time in preparing the code for maintenance.
  7. Perceived lack of time to write good comments or to comment at all. Deadlines are the main killer of good documentation and good comments are also sacrificed in the process. Some people feel that commenting while writing the code interrupts their thought flow so they postpone it for the end, and then commenting actually never happens. Other people like to start by writing comments to outline what they have to implement. After the implementation is added they don’t review the comments to remove the obvious and to replace them with explanations.
  8. There is interest in lack of comments or in bad/useless comments. There are programmers out there who create useless comments (or use no comments at all) as a job security technique. This behavior can be observed also at some companies that provide open source free code and have a business model based on providing support and other services for that code. They feel compelled to provide as little free guidance as possible. Can you think of some examples? :) In the same spirit some contractors might try to get maintenance contracts in continuation of development contracts by obscuring information with lack of good comments.

First of all the quality of the comments in the code is an indicator of the overall code quality. I never encountered great code with bad comments. Good programmers keep the code neatly formatted and well commented.

The effects of poor or non-existing comments is felt long after the code is sent in production.Bad comments make the life of the maintenance developer hell. As a result of the poor understanding of the code intent bugs are introduced during maintenance and modification and can cause significant costs and business loss over the lifetime of a product.

How to write good comments

In order to write good comments first of all you have to care. You have to care about the quality of your work, about your customer and employer and you have to deeply care about the poor souls who will try to fix or change your code sometimes many years after you forgot you ever wrote it.

If you don’t care probably you didn’t make it this far in the article.

If you do care than take the list of “good comments” traits from the beginning of this post and pin it to the wall next to your monitor. Every time when you feel a piece of code is ready to be stored in your code repository review it thinking about all those points and try to make your intent and context as clear as possible for the next fellow programmer.
That list can be the base for a quality standard for comments in your company/group/team. Don’t make it a dogma and don’t transform it in bureaucracy.
Offer feedback to your colleagues and training to new team members. Make them care about their work and about the developer maintenance. You can be one at some moment in your life.

17 thoughts on “How bad comments are born in your code”

  1. Just to add my two cents:

    Describing the intent, requirements, etc is only actually necessary if you are doing something that is not the common practice for the intended audience of this code.

    For example:

    int global_cache[10];

    void update_global_cache_from_local()
    {
    for(int i = 0; i < 10; i++)
    {
    global_cache[i] = get_local_cache_entry(i);
    }
    }

    There aren’t any surprises in this code. Both the caller and the maintainer of this code can very easily see what it is doing and have a good idea of why.
    The reasoning for this type of caching system could be placed at the top of the file in a big comment, or better yet in a design document.

    However:

    int global_cache[10];

    void update_global_cache_from_local()
    {
    // Unrolled loop for improved performance
    global_cache[0] = get_local_cache_entry(0);
    global_cache[1] = get_local_cache_entry(1);
    global_cache[2] = get_local_cache_entry(2);
    global_cache[3] = get_local_cache_entry(3);
    global_cache[4] = get_local_cache_entry(4);
    global_cache[5] = get_local_cache_entry(5);
    global_cache[6] = get_local_cache_entry(6);
    global_cache[7] = get_local_cache_entry(7);
    global_cache[8] = get_local_cache_entry(8);
    global_cache[9] = get_local_cache_entry(9);
    }

    In this case, we are using an uncommon implementation, and so should describe the implementation (unrolled loop), and the reasoning behind it (performance).

  2. Good articles, but I disagree with these two points :

    -> Explain why the code was modified/fixed and mention the bug ID (at maintenance)
    -> Describe how the code was modified/fixed and what the desired effects are (at maintenance)

    I think it’s more the version control’s job to handle this.

  3. I’ve read both your post and the two you mentioned in the beginning and … well, I’m rather perplexed.
    We have to remember that we’are talking about commenting code; the why the code is designed like this, as well as the why the business process is designed like this should not go into the code in my opinion … they should go in the documents describing the architecture and/or the detailed design. Only “micro”-decision should be commented in the code; all the rest should go in separate documents. Yes it’s a hassle to write them in the first place and, moreover, to strive for keeping them up-to-date … but such an effort will more often then not be well rewarded during the whole software life.

    As thibault’s comment stresses, sometimes there’s some confusion about software processes and/or software best practices.

    By the way … GREAT BLOG!!! It’s often very useful – and always a pleasure – to read your posts.

  4. @Wolter
    The audience of the code is the customer. The audience of the comments is the maintenance developer. It is hard to know in advance sometimes years in advance what is common practice for him. But yes I agree comments should be kept to the necessary minimum while explaining the intent when things are not obvious.

    @thibault
    I agree that most information about maintenance changes should go in the version control repository. But version control systems are not born equal. Also people tend to check in multiple files at once with only a general comment about the problem and the fix. Sometimes a fix introduces another problem and the person investigating the new problem is not the same. A comment in the code can help at debug time producing an “aha” moment. Then the different versions in the repositories will be compared.

    @milkyway
    I didn’t mean to put all the design in comments :) What I want to say is that comments are useful when they help the reader understand not only the code but also the intent and the context of the intent. And this should be done with a minimum amount of comments. The list I presented is just a filter for good comments in my opinion. Also keep in mind that in most cases the documents quickly get out of sync with the code and they are useless at maintenance time. Not a desired thing but just how reality works.

  5. @Daniel
    The customer is the audience of the finished product. In general, the customer’s interest in the source code is simply possession in case your company goes bust.
    The audience of the code (and comments) is the maintainer. The design document is the map, the code is the forest, and the comments are the trail of breadcrumbs and marks on various trees.

    Common practice will change over time. However, since you are not in possession of a crystal ball, your nest best course of action is to document whatever is not obvious (i.e. not common practice) today lest you clutter the code as you hedge your bets. Of course, understanding the knowledge gap between yourself and your probable peers is a challenge in itself.

  6. @Wolter
    I simply agree :) I like the breadcrumbs analogy. As I mentioned before I think good comments are born when you make an educated decision to put them in the code to be useful for the maintainer. When you think about your comments keeping the maintainer in mind you will write better and more useful comments.

  7. @Daniel
    I agree on that, Daniel. In fact I said that “micro”-decision should be commented in the code. I can also add that they must!

    Experience shows that you’re right: in most cases the documents quickly get out of sync with the code and they are useless at maintenance time. But this is not due to documents in itself, it has to do with people: everyone likes to write code but almost nobody likes to write/update documents – this is very true for me, at least! But I’ve learned the hard way that writing good documents, keeping them up-to-date and then referring back to them is not only of great help but moreover a cost-effective practice.
    Of course, it’s up to the management to establish a process about handling project documentation in a proper manner.

    I know agile practitioners will strongly disagree on this issue but … I’m not very fond of most agile practices, sorry :-(

  8. To the question “If code comments are so important then why so much code is poorly commented?”

    I’ll have strongly deseagree with reasons 1,2,3. In these cases you should change the code not adding comments.

  9. The article is indeed reflective of reality. I wonder though if you could have enhanced it to also touch on the topic of SCM submissions. I noticed the other day in our SCM logs a software change with entry like this: “* added some more stuff”. I wish I could tell that guy what I think about it.

    Anyway, my point is that it is also very important to attach very descriptive logs to each submission, to both make revisions searches easy and make your reasons understood.

  10. @Samori

    In an ideal world, you wouldn’t write “difficult to unterstand” code, and thus wouldn’t have to comment it. In the real world, sadly, this is sometimes neccessary. Just two examples: Imagine you’re writing an algorithm to extract some information from a list, and you’re using the fact that the list has been sorted in a step before that. This is a very important information for a comment (and, if possible, an assertion): The code might look wrong to somebody who thinks list is not sorted. And it might indeed do the wrong thing, if somebody changed the code that sorts the list (so, a comment there might not hurt, too). Of course you could sort again, just in case, but that would be inefficient.

    Second example: Imagine you’re doing signal processing; You’re extracting some kind of information out of a signal – in order to do that, you’ll have to make some assumptions about the shape of the signal (e.g. is it periodic, is it noisy?). These assumptions often can’t be encoded in an assertion, but they make invaluable comments, because it’s very hard to really understand what your code is supposed to do if you don’t have the neccessary info about the input data.

  11. I respectfully but largely disagree with your opinion. The better my code is, the less comments I have, because the code is self-explanatory. If not, I refactor.
    You mention that unmaintained comments are bad comments. The best way to avoid it is too have as little comments as possible. Instead, have unit tests, which explain with great clarity the code intention – and which you will have to modify if you change your code. Comments are just hard to maintain, harder than tests or code itself.
    Finally, I heard one of the authors of “Beautiful Code” in a conference give this word of advice: the only valid comment to put in code is “DO NOT CHANGE THIS”…

  12. I completely agree with this article, some comments are absolutely invaluable.

    No matter how good your code is and how many unit tests you have, sometimes the right comment in the right place makes all the difference 3 years down the line.

  13. @Mathias
    The problem I see with your approach is fact that the code is good in your opinion and the self-explanatory to you at that very moment. Did you try to read your own code after 5 years? Or after 5 years of maintenance done by other people?
    The fact that something is hard doesn’t mean we should avoid it. It means we should understand it better and do it better. If we go down on this path we could say the best way to have less bugs is to have less code. But wait, unit tests are more code and they increase the chance of bugs. Or we can say the better our code is the less unit tests we need…
    You have to modify unit tests when you change your code only if the interfaces change. Otherwise nothing will tell the maintenance programmer to change the test. And I have seen situations where the test wasn’t failing but the modified tested code was wrong.

  14. @Daniel
    Actually, I have to look back at my own code pretty often, that is way I am super obsessive about refactoring. Fortunately, I have always been working with a small team, so I did not have to deal with the problem of maintenance done by other (not-so-good) people ;-)
    Jeff Atwood actually stated much better than I would my opinion in this great post:
    While comments are neither inherently good or bad, they are frequently used as a crutch. You should always write your code as if comments didn’t exist. This forces you to write your code in the simplest, plainest, most self-documenting way you can humanly come up with.

Comments are closed.