PHP in Action Rotating Header Image

How code comments deteriorate

There was a lot of disagreement on the value of code comments after my earlier post Comments considered harmful. Perhaps the most important objection that was raised was the idea that it’s OK to improve the code, but it’s even better to keep the comments in addition to the improved code.

As one of the critics expressed it:

No, comments are there to comment. Period.
That has nothing to do with how good is your code.
You can write perfectly clean code and add good comments to it. Nothing wrong with that.

This is one of those ideas that seem obviously true in theory, but fail to work in practice. The reason is that comments get out of sync with the code. The comments rot, or rather, their meaning does. They become more and more misleading as the code gets changed and the comments are not adequately updated.

Let me give you an example. But first, I want to make it clear that I don’t think code comments are always a bad thing. Sometimes, they are necessary. But much less often than people think.

API documentation is often indispensible, but that’s really a different matter. When API documentation is generated from comments in front of each method, the primary purpose is to explain how the code can be used, not how it works. In fact, you might say they are code comments only in a syntactical sense.

On to the example. One of the comments to my blog post presented a code snippet that illustrates my point well. It’s supposed to be a example of a useful inline comment in code.

// first handle the case where no records were found
if ($records == 0) {
    return false;
}

Is this really an case of good commenting? I don’t think so. If it’s hard to understand that $records == 0 means that no records were found, we can change the code to make it easier. The simplest way to do it is to rename the variable to something like $numberOfRecordsFound or $numRecordsFound. Or extract a method. But typically, it’s possible and preferable to avoid this kind of check altogether.

Anyway, the comment is unnecessary. But as I only realized a while later, it’s also misleading. Does the code “handle the case where no records were found”? No, it leaves it to the calling function to handle the case. The one line that returns false is not handling anything, it’s just passing a message.

So the comment is already misleading, never mind what will happen when someone changes the code and neglects to update the comment. For example, let’s say the next programmer to work on this code is in hurry to fix a bug. Now maybe the code will look like this:

// first handle the case where no records were found
if ($records == 0 && $state == ACTIVE) {
    return false;
}

The programmer wonders briefly whether the comment is still fully appropriate, is unsure, and decides to do nothing about it (or postpones the decision and forgets about it). Now, perhaps (we can’t quite tell without the full context), the comment is even more misleading.

In the next round, yet another programmer comes along, makes some more code changes and wonders: “Should I update the comment? It looks all wrong to me, but it was probably written by someone with deeper insignt into the code. Better leave it alone.”

The code would have been better off without the comment, but no one wants to delete it, especially since they have been told that comments are so important. It’s a downward spiral: the code changes make the comments misleading less chance that they will

Comments that lie are worse than no comments, and in practice they tend to big liars.

Share/Save/Bookmark

10 Comments

  1. I think you could come with bad usage examples for anything, but this does not proof that comments are evil.

    Eli says: “Inline comments that explain what the actual lines of code are doing are absolutely vital to enabling other programmers to pick up your code, understand it, and augment it.”

    I think it is a bad concept and the mentioned one line comment for every line of code is very bad habit.

    The code should be self explanatory about what it does (I agree on this with dagfinn), and with good naming (and being passionate about writing understandable code) usually you can achieve this. Ok, sometimes it is easier writing a little comment than refactoring the code, but if you are writing in a comment about WHAT it is a bad small and signs that maybe you should refactor your code.

    But, I think comments have their place, and their importance is to explain why did you choose a given solution or what was the premise which was constraint you to use some not obvious solution.

    And another important field is where a code comment could be very invaluable: to note the history of a piece of code. Sometimes the path to a given solution (through some gotchas) is much important than the current behavior, and it is very important to change the code into the proper direction.

    p.s.: My English is not the best but I hope I could explain what I think.

  2. nico says:

    Hi, first of all thanks for writing a post out of my comment :)

    I would just like to clarify a couple of things.

    1) my comment was intended to say that writing comments does not make your code good or bad. Code is code, comments are comments. You can have all the possible combinations of perfect/good/medium/bad/afwul code and comments that you can think of.

    2) The example you make in this post is probably not the best. I perfectly agree with you: THAT comment is useless. The fact is: the programmer who changed the code may have added a meaningful comment instead!

    Like

    // We only need to return false if $state is active, otherwise bla bla bla
    (if $records == 0 && $state == ACTIVE)
    {
    return false;
    }

    This type of comment is not trivial as the one you wrote because it does not explain what the code does but WHY it does that.

    It’s like saying

    // Set a = 1
    $a = 1;

    Ok, that’s really stupid

    But

    // We need to initialise a to 1 because xxxx
    $a = 1;

    That could be more interesting (depending on the situation)

    That said, I don’t want to say that every single line should be commented, of course. But I still prefer one line of comments than aVariableWithAnExtraLongNameThatTakesMeAgesToRead.

    Of course, at some point it all comes down to the specific situation and to personal taste.

    nico

  3. Sebs says:

    if you have coding conventions in place that limit line length

    aVariableWithAnExtraLongNameThatTakesMeAgesToRead

    migt be a problem. ;)

  4. Martin Fjordvald says:

    Two seconds to read a variable name beats half an hour trying to make sense of code.

    That said though, the argument here uses false logic, it’s not the comment that’s bad, it’s the programmers who makes bad decisions. Do you blame the gun too when it’s the human that pulls the trigger?

    But then again, it’s much more fun to argue that comments are bad than that humans just aren’t logically capable of programming properly because we’ll always postpone things and look for the easy way out.

  5. Roger says:

    I think that you could look at this as situational.

    A freelancer, coding a site/app for a specific client may wish to comment the application in such a way that he leaves clues for himself in case there are changes to the code later. No-one is expected to take on the code and amend it other than himself , as far as he is concerned and the contract did not provide funding for a full design package, but rather a seat-of-the pants, get-it-up there -asap coding style.

    A coder on a large team, with mixed responsibilities, building a package that will be shared and probably maintained by other, might assume that someone coming in to code needs only the signpost comments to tell them which segment provides the service they are seeking to enhance/fix.

    Both are perfectly valid viewpoints and would have a reason to pick one approach over another.

    short summary – not all code is designed to be maintained, or even to be good code. Sometimes it just has to work in this instance.

    I love the idea of using variable names in a more commenty manner, and could see some good uses for it, but have also been frustrated by code written to standards with the variable named and typed and packaged to the point where it is impossible to navigate the code without a full data dictionary.

    This is a great series of posts, but I hope that those who feel it necessary to prove Dagfin wrong will at least get a sense of how comments can be both under and over-utilized.

    Roger

  6. Shaun says:

    The problem is in the teaching of programming. It is taught always to comment code! I think this is mainly for the teacher to figure out what the heck you are doing. I also think that this recently has been something that has changed. It used to be that everyone commented code and now things are changing to non comments. Personally I like code comments especially the funny ones left by coders years ago. Maybe it’s just a personal preference.

  7. FTA:

    The reason is that comments get out of sync with the code. The comments rot, or rather, their meaning does. They become more and more misleading as the code gets changed and the comments are not adequately updated.

    That happens not because comments are bad, but because the coder isn’t doing his job properly. A programmer who writes bad comments is just as much a threat to a code base as a programmer who writes bad code. Period, plain and simple. Comment rot is no more or less an issue than code rot, which also happens to projects over time unless you work to prevent it.

    A decently professional project will have gatekeepers on commits, or at least branch merges, that check for not just code quality but comment quality. I’ve seen patches rejected from the open source project I work on because their comments were wrong, incomplete, or inconsistent. That is how it should be, and I wouldn’t want to work on a code base where that’s not the case.

    The examples in the original post above are also easy strawmen. As a recent example, I was working on a bit of code where in order to work around a bit of Ajax-related weirdness I had to break into 2 code paths with a conditional. Just reading the code without any context it was totally non-obvious why we had to do that, even to me and I’d just written it. I therefore included about 8 lines of code comment above it (the code block in question was around 15 lines) explaining what we were doing, why, and the assumptions we are making in the code. That means my colleague coming back in 3 months (which could well be me) will see the code block, go “wtf?”, see the comment, go “oh, OK”, and not spent 5 hours trying to unbreak something because he thought he could simplify the code without understanding it.

    That’s good code commenting. If you don’t provide me, as a later reader of your code, with that sort of background information around tricky or unintuitive logic, then I don’t want to work with you because you’re wasting my time.

  8. dagfinn says:

    In your weirdness scenario, did you consider the possibility of changing the code to make it not so “totally non-obvious” instead of adding the comment? That’s the point I’m making, and you’re not making it clear that you’re addressing it.

    I’m claiming that in most (but not all) cases there is a better alternative to comments.

    But, to quote my first post, “adding comments to unreadable code is better than leaving it the way it is”. If we interpret “unreadable” loosely as “hard to understand”, does your weirdness example tell us anything more than that?

  9. Allain says:

    Is the syntax in your examples correct?

    shouldn’t they read:
    if ($records == 0) { …

    rather than
    (if $records == 0) { …

  10. dagfinn says:

    Of course, how silly of me. My lame excuse is that I copied it from a comment someone else wrote. ;-)

    I’ve fixed it now.

Leave a Reply