NDepend

Improve your .NET code quality with NDepend

Is There a Correct Way to Comment Your Code?

Given that I both consult and do a number of public things (like blogging), I field a lot of questions.  As a result, the subject of code comments comes up from time to time.  I’ll offer my take on the correct way to comment code.  But remember that I am a consultant, so I always have a knee-jerk response to say that it depends.

Before we get to my take, though, let’s go watch programmers do what we love to do on subjects like this: argue angrily.  On the subject of comments, programmers seem to fall roughly into two camps.  These include the “clean code needs no comments” camp and the “professionalism means commenting” camp.  To wit:

Chances are, if you need to comment then something needs to be refactored. If that which needs to be refactored is not under your control then the comment is warranted.

And then, on the other side:

If you’re seriously questioning the value of writing comments, then I’d have to include you in the group of “junior programmers,” too.  Comments are absolutely crucial.

Thins would probably go downhill from there fast, except that people curate Stack Overflow against overt squabbling.

Splitting the Difference on Commenting

Whenever two sides entrench on a matter, diplomats of the community seek to find common ground.  When it comes to code comments, this generally takes the form of adages about expressing the why in comments.  For example, consider this pithy rule of thumb from the Stack Overflow thread.

Good programmers comment their code.

Great programmers tell you why a particular implementation was chosen.

Master programmers tell you why other implementations were not chosen.

Jeff Atwood has addressed this subject a few different times.

When you’ve rewritten, refactored, and rearchitected your code a dozen times to make it easy for your fellow developers to read and understand — when you can’t possibly imagine any conceivable way your code could be changed to become more straightforward and obvious — then, and only then, should you feel compelled to add a comment explaining what your code does.

Junior developers rely on comments to tell the story when they should be relying on the code to tell the story.

And so, as with any middle ground compromise, both entrenched sides have something to like (and hate).  Thus, you might say that whatever consensus exists among programmers, it leans toward a “correct way” that involves commenting about why.

The Main Problem with Comments

So far, I’ve offered adages and people’s opinions.  But I’ve done so without really diving into their underlying rationale.  In some cases, I couldn’t because they omitted it.  And, in other cases, I simply didn’t fit it into the quote.  Presumably, they all have their rationale.  But I’ll speak in broader terms here.

Comments have an obvious purpose: communication and clarity.  And they have an obvious downside: time spent writing them.  If the problem were simply a matter of weighing the time investment in commenting against the benefit in clarity, then they’d be something of a no-brainer.  But comments have a far more destructive downside.  On a long enough timeline, they often lie.

What happened here?  When you put on your code archaeology hat, you’ll probably conclude that a guard condition once existed.  Someone deleted that guard condition, but didn’t think to update the now-nonsensical comment.  Oops.

This hints at the inherent underlying problem.  Specifically, comments represent a non-compiled, non-enforced relationship between code and meta knowledge about code.  Adding comments adds cognitive maintenance burden for everyone that touches the code in the future.  And since nothing forces people to update the comments, they get out of sync.  This creates the possibility for negative returns on the effort of commenting.

Addressing the Burden of Comment Maintenance

At this point, I have yet to say anything controversial.  I think all parties can agree that commenting creates additional maintenance burden and seeks to pay for that burden with the clarity it provides.  Where people diverge, I suspect, has to do with the burden of the maintenance work.

Proponents of the code comment would argue that maintaining comments simply comes as part of maintaining code.  Opponents would counter that all such effort should go toward making the code itself clearer.  No comments, no comment maintenance burden, and no chance for comments to lie.

While I can see both perspectives, I’ll point out that only one lies counter to human nature.  Saying that all developers have a duty to comment places burden on people, some of whom will never accept that burden.  In doing this, you become the guy at the office demanding that everyone keep the single serving coffee pods in alphabetical order.  People won’t do it, and you will only achieve satisfaction by stamping your foot, getting angry, and haranguing people.

Even if you win, it would require draconian measures and result in resentment.  You might find yourself winning a Pyrrhic victory.  The people you badger have no natural incentive to comply with your demands.

A Main Heuristic for Commenting Code

Perhaps you can demand this high standard of professionalism.  And perhaps you find yourself in a like-minded group where this works.  But most likely, it just results in endless contention between you and others.  And, if you don’t execute the comment diligence flawlessly, the comments age poorly and have negative value.

As a result, I offer the heuristic that the correct way to comment is to avoid them as much as humanly possible.

Note now that I haven’t offered any sort of absolutes.  I haven’t said that you shouldn’t write comments.  Rather, I’m offering something a lot more nuanced.  The most likely outcome for a comment involves negative value on a long timeline, like playing games in a casino.  But I won’t tell you not to play blackjack and I won’t tell you not to comment.  I’ll just point out that minimizing these activities makes for a good life strategy.

So approach commenting skeptically.

Sometimes You Need Comments

That said, you do have situations that absolutely demand code comments.  For instance, some organizations have mandates for legal/copyright comments in each file.  By all means, add those comments when required.  (For this purpose, you might want to enlist a generator or something to avoid wasting your time.)

In addition you’ll want to add method header comments for the sake of documentation and Intellisense.  When you write code for consumption by others, these comments constitute de facto end user documentation.  In this situation, the value tends to outweigh the maintenance burden, since it impacts your product’s usability.

And, finally, sometimes you have something mind boggling in your code.  Sometimes you’ve refactored, cleaned up, and done everything humanly possible.  But you still have something that will confuse and stymie.  Far be it from me to say you shouldn’t explain with with a couple of slashes and some prose.  Do what you need to do.

But as you go, recognize comments for what they are.  They create a maintenance burden and have a negative expected outcome.  So use them cautiously, pick better options when you can, and understand that no amount of righteous indignation on your part will alter the human nature of others.

Published by

Erik Dietrich

I’m a passionate software developer and active blogger. Read about me at my site.

Comments:

  1. I also comment urls to stack overflow or other sites I have used for code snippets. Part as a nod to the original authors and part to have a starting point if a bug is found or evolves with it in the future.

    I’m surprised there isn’t a util somewhere that when you try to commit code Which has comments you have to explicitly vouch for them to make remembering to update a part of the process.

  2. Seems like largely sensible advice.

    I will add that I find comments have much more value top-down rather than bottom up. By this I mean that comments against a class – describing the purpose and intended use without getting into technical specifics – I find the most useful of any comments when I’m having to maintain unfamilar code. Next most useful are method comments; lastly, least useful I find, are comments for specific lines of code.

    Although for me the most useful, higher-level comments in my experience are the most likely to be neglected.

    Higher level comments are also the least likely to degrade as changes to the implementation specifics of a class should not affect the purpose and use of it.

    1. Personally, I consider comments most useful for modules, classes, methods … briefly supply information designating what it is and how to use it. I think this is especially valuable when the comments are styled such that an auto-doc process can automatically generate an up-to-date “manual” from the code for reference.

  3. In line with your coffee analogy, people who refuse to maintain comments when editing code are like the guy who spills coffee all over the counter, looks around, sees that no one is looking, and just walks away. Your mother doesn’t work here, clean up after yourself.

  4. I would put myself into the junior programmers group, if not even further down the chain. I am self taught. Program only for fun in my spare time, and senior programmers would probably either cry or laugh if they saw my code. 😉

    I use comments at the top of each function as a reminder what I wanted the function todo (including variables supplied to the function.) And I also include comments on specific lines when I’ve had trouble getting that line of code to work they way I wanted it to.
    Commenting just makes it so much easier for me when (not if) I have to fix something in my code.

  5. Another vote for ‘why’. In my previous life as a contractor, understanding an application written by someone else was always difficult, often impossible. Comments, if any, would just explain what each line of code did, which was largely obvious. But the gap between that and what it meant in terms of the application as a whole was all too frequently unbridgeable. Well written comments form that bridge. To quote ‘Code Complete’ “Comment at the level of intent.”

  6. In the industry that I am in, electrical test engineering, comments are a very useful way of communication, at points in the code, between those of us that understand the Hardware that is being controlled (test engineers) and those that don’t (software engineers).
    This, I am sure, may apply to many other scientific and industrial applications – comments that are not explaining the code for what is it in a pure computer science term but in terms relating to the application of the code to the real world.

    Now, I am going to go off-track from commenting here, but bear with me because it is related:
    I am not a computer scientist or software engineer and I was writing some C++ code the other day and needed to refresh my memory on how C++ handled bit-wise manipulation of data (AND, OR, XOR, etc.).
    The article I came across in my online search did a good job of explaining this but I was kind of shocked at the articles explanation of why one would want to perform bit-wise manipulation; the article stated that in an earlier era of lower memory computers, bit-wise manipulation was needed to conserve memory space and now it was archaic and no longer needed but the article would cover it for ‘historical purposes’.
    Here is a case where a software engineer / programmer has become immersed in coding and lost sight of the fact that software often controls ‘real hardware’ and real hardware is very often controlled by these ‘individual bits’ of data.

    So, my point is that sometimes comments can be very crucial in tying the ‘mundane code’ back to what it is actually doing or effecting/controlling in the ‘real world’.

  7. Thanks for exposing your position by taking hindsight. The heuristic I’ve come to is “Imagine what you would need to tell to someone who is reading your code, if you were sitting next to them. This is what you put in comments.”, would love to hear what you think of it.

  8. When confronted with code that contains a lot of comments I generally delete all those comments first to make the code readable. Too much comments will distract your attention from the actual code. Comments should clarify stuff that is not obvious. This also means that in most cases the code could be refactored to make the comments obsolete. So I do agree with the statement that you should minimise the use of comments.

    1. I wrote a very simple application years ago for my own personal use called “ckiller”. It would scan through a file and remove all of the comments so that I could simply focus on the code itself 😛

  9. Recently, my approach has been: always have a header comment at the top of each file, then “comment” via logging/print statements. This kills 2 birds with one stone: I get the benefit of comments and don’t have to add logging later when I inevitably am diagnosing a bug. Obviously it doesn’t work or make sense 100% of the time, but you’d be surprised how much time ends up being saved overall.

    1. I agree with this logging approach. We us a logger that allows the end user to set a log level at run-time (DEBUG, INFO, ERROR, PRODUCTION) and I use log statements to give more and more info as the log level goes from PRODUCTION (very little) to DEBUG (maybe a little overkill).

      We also use documentation generating tools so we format our header comments appropriately for those tools.

      We are writing a code library that other engineers will assemble into a test program for testing semiconductor devices in production, so documentation of our code is important and the easiest way is to write well structured comments and use the aforementioned tools to turn those comments into HTML, Markdown or PDF based docs.

      Whenever I set out to write a new piece of code (in our industry it is called a test template) I usually START with the header comment and think through all the input parameters the user will provide and write down, in fair detail, what the code will do, and what outputs it will produce and what error or exceptions can occur, etc.

      I find this can help a great deal in planning to write the code instead of just plowing straight into the coding.

      I know this doesn’t apply to all situations or all types of software coding, but it works well in my industry and it may apply to some others.

  10. my view on code documentation is that it’s good to have BUT only when you also have some sort of external documentation repository to go with it. I’m doing my college placement working on mainframe applications at a bank. They have great comments, but without an underlying knowledge of the application itself those comments are basically useless unless I get someone to explain it.

    Recently there’s been a push to having external documents explaining the “why” for each part of an application. I fully support this approach since it means that comments can be used more as a concise reminder than as a way of fully explaining your logic. An external document wiki also encourages communal documentation of the “why” and helps cut down on outdated documentation.

  11. I’d add that production code is written in a greater context than just the implementation, so it’s often useful to the team to have comments about the big picture. Production code is expected to last a long time – even decades – and comments help in that case through team, industry, and technology changes.

    Optimizations or unintuitive looking bug fixes usually need commenting so some eager junior doesn’t come along and “clean it up” back to a slower broken state.

    Non-production code, throwaway code, one-off utility code, in them comments serve much less use, of course. Unless it’s a prototype that will be used as a reference to write the production code!

    I’ve had (and once was) plenty of junior or mid level programmers who’ve never worked on projects big enough to require code maintenance, or had code last more than a few months, or on a codebase that solves problems larger than can fit in their head. They tend not to see the need for comments or they write comments that duplicate code.

    All that, and I still don’t meet my own commenting standards, is a constant battle to reach the ideal! And @Bob – love it!

  12. “On a long enough timeline, they often lie.” – long enough like later the same afternoon?

    I write comments when I do something weird or out of character, or I’m forced to do something really stupid to get around the unicode requirement you can’t turn off anymore just to copy a few strings. These comments are for myself, because, unlike 98% of programmers, my plan is to stick around and maintain my own code instead of dumping it on somebody that just walked in because somebody just offered me 3% more to move across country. I try to have long term relationships with employers and clients and by definition, my work. I’ve been largely successful in doing so, and I realize this makes me an oddball among oddballs.

    As far as other people’s code and their comments, I’ve frequently found the comments so obtrusive that I ran the source code through a little filter to completely remove them. They either stated the obvious or outright lied, and even occasionally contained a dissertation on the brilliance of the coder. The brilliance is in the code, and on the rare occasion I’ve encountered brilliant code after a couple hours of head-scratching WTF, I have the light bulb moment where I see and say AHA! That’s how *I* would have done it!

    I believe all programmers who ever accomplish anything are stick-and-rudder guys who don’t pay much attention to the blather of high-level spec nor waste time on low-level spec that takes longer to write than code, and both become obsolete the moment functioning code is created. In other words, maybe one percent. When I’m working with a rookie that just stepped out of Ohio State with a masters, who is telling me what my customers want but can’t read a raw data stream, I am probably not going to give a lot of credence to his commenting and in fact I’d prefer he spent his time coding. But really, seriously, I’d rather do it myself. I attribute my loss of a high paying job not too long ago, to doing only the back end of a client-server app because the client side had to be done by a “web guy” and I wasn’t. I never should have allowed that to happen. Web guy doesn’t work there anymore either – that would be the second web guy, who spent his first year rewriting everything the first web guy did – making it worse, while I trod water and waited for something to happen.

    Lesson learned… do it yourself.

  13. Sometimes you need comments, sometimes you should comment, and sometimes you shouldn’t comment. Commenting is a completely different art than programming. It is technical writing. You are communicating with your audience, which could be someone five years from today. But most programmers just want to learn how to program and not how to write.

    //Returns x + y or, if x or y is less than zero, throws an exception
    This is a classic example of a comment that should not have been written in the first place. It is just restating what the code was or was supposed to do. Something that reading the code already gives you. A useful comment would be an explanation why negative values are not allowed.

    Finally, anyone who thinks code is self documenting has never worked on an international project. When half your programmers have English as their second or third language, you get some very interesting names for variables and methods. Even British English is different than American English. Be practical. You are not going to teach everyone to use the same dialect of English. Instead, clearly comment your public methods and attributes so that others will use them properly. Commenting improper usages can also be valuable. And avoid ambiguous comments that can be read in different ways – which with international teams is very easy to do.

  14. I don’t think code comments are equivalent to techwriting. Most programmers aren’t good tech writers and vice versa. Tech writing is rarely done anyway – who has a user manual for anything anymore? Got a new app for your phone? Good luck figuring out what gesture does what. Of more use to a programmer is a halfway decent readme.txt file to accompany a piece of code. I find it extremely difficult to read code that is loaded up with wordy comments – especially those that add vertical space and cut by half or more the number of visible actual code lines in your editor. Editors highlighting comments a different color are marginally helpful but just really add to the distraction of calling up code and not seeing code.

    Then again I find features like C++ overloads to be obtuse. You have to write a separate call for each overload, and each one ends up usually calling the same root. Why not give them different names, so when your intellisense (assuming it functions at all) pops up, you don’t have 11 overloads to flip through. I think I was a better thinker without all these helping hands because I had to remember things, and be succinct. Overloads allow code to look like one thing and do another – what, requiring another comment to indicate which overload is being invoked? Or maybe, if it had a different name that would be obvious from the beginning.

  15. Hacker News at https://news.ycombinator.com/item?id=14379371 lured me here because the issue of code comments is causing me a lot of anguish. For open-source artificial intelligence I write long, complex programs in Forth, Perl and JavaScript. I like to clarify my code with comments, and I engage in some commenting practices which seem weird to other Netizens. For instance, I like to insert a date like today’s 2017-05-19 at the start of each comment, so that over time I can see how old each line of code is. Another thing I do, but not so weird, is that when I comment out a line of previously active code, I keep it in through at at least one public release of the open-source AI software, so that AI enthusiasts can see exactly what I am doing when I make a change to the free AI code — which may think in English or German or Russian. Recently I have been anguished with the idea of removing almost all the comments from my AI code so that it looks more refined and more professional. Or, maybe I should publish both the commented code as say, Ghost.pl and the uncommented code as the perlmind.pl program. So I am glad to read this discussion on the problems of commenting code.

  16. Definitely in the why camp. I don’t need to know that this line does say add a and b and puts it in c since I can read that. However I might want a line to point out that I used these 3 lines of code because this compiler doesn’t support a function that would normally be there. (Which I saw with a missing time function in C++) But I’m also a fan of writing function comments from the point of view of what you’d see in a users manual so I don’t need to reverse engineer a function in order to call it. They should be vague about implementation but that comment is a contract between the caller of the function and the writer of the function. In all seriousness if I read some function documentation in say the STL manual and it says “This function returns either 0 or 1 but in reality returns 0, 1, or 2 this isn’t proof that documentation isn’t worth doing. (Which is kind of what I see anti-comment people often effectively argue.)

  17. Interesting article and discussion.

    I comment public classes, methods, and properties, for the same reason Microsoft, Google, and most professional software companies do…so I can generate documentation for future consumers. n my opinion, since I often lookup methods/classes from these companies, I’ve indirectly supported the argument for comments in these locations.

    I’ve been at this a very long time and seen abuses on both sides of this argument. Heck, in the past, I’ve been guilty of committing offenses on both sides.

    I’ve encountered far too many programmers who argue against comments, explaining how readable code can be, and then produce an inscrutable mess, albeit with long (and often useless) method and variable names.

    I’ve seen programmers who write novels that distract terribly. Often, these comments add far more information about their egos than about their code. I’ve seen distracting and obvious comments like “increment x” for “x = x + 1”. Personally, I’ve come to find comments, within methods, to be a major distraction.

    My take, add moderate comments on public classes, public methods, and private methods that are particularly complex. If your comment is longer than a medium-sized paragraph, its probably too long. If its shorter than a sentence, its definitely too short 🙂

    Avoid commenting within a method. This is almost always an excuse. If you think “I need to”, you should definitely consider breaking that code out into its own method.

    Like most things in life, in moderation, commenting can be helpful. Its been a long evolution for me to come to this opinion.

    My initial inclination was to over comment. In my defense, this was back in the dark ages when function and variable names often had very short length limitations. Over time, as these limits were relaxed and editors started featuring auto-complete, I evolved.

    At some point, I “over-evolved” and stopped commenting. You may discover the pit falls of this, if you need to revisit your own code, years later. Here, I re-visited code I was certain, at the time, was a master piece of clarity. Years later, it was not.

    Following this, I made two improvements. First, I tried even harder to write clean code. Second, I admitted, to myself, that a few comments might not be the worst thing in the world.

    I suspect that, if one survives long enough in this industry, most eventually learn the benefits of compromise. But, then again, I’ve met too many folks who know, with certainty, the “right way” to do things. I’ve been one myself…too often.

    Whatever you choose, I humbly suggest maintaining a healthy bit of skepticism about how “right” you are. Its way too easy to believe your own BS. Everyone has some…some way more than others 🙂

    1. “At some point, I “over-evolved” and stopped commenting. You may discover the pit falls of this, if you need to revisit your own code, years later. Here, I re-visited code I was certain, at the time, was a master piece of clarity. Years later, it was not.”

      Indeed, over the years I’ve found that it is most often me who is the one to come back to my own code (years) later, and to suffer from the lack of comments. What’s more, I’ve found that my way of thinking changes notably over time: what I thought to be well-structured and clever a year ago, I now may regard as less than stellar, or worse, hard to understand and maintain. Plus, depending on the context of that code, it might require significant work just to understand how it’s meant to operate.

      Therefore I write my comments in such a way that someone who isn’t famililar with the topic still can grasp it (provided a sufficient level of intelligence and basic knowledge). That way, when I come back later, I can understand what’s up without having to dig through the entire context. For hours. Again. And again.

  18. Not putting in comments that explain classes and methods (and especially interactions with distant parts of the code) is arrogant and lazy. At best it increases the time it takes for a new person to understand the code. It can also lead to incorrect modifications by a maintenance programmer.

    There’s a real cost to the attitude “My code is so clear it doesn’t need comments!”. Of course it’s clear to YOU — you just wrote it!

  19. Programmers have great memory for the things they have written so they don’t think they need comments and since most software nowadays has a shorter shelf life I can see the rationale. However if you tend to be involved in a lot of projects over the course of a year or so and have to revisit key parts of the code, you might think twice about not leaving comments, reminders, todos and warnings.

  20. The only comments guaranteed to stay in sync with the code are code-reviewed comments. This actually makes sense when you use stuff like java-doc comments. (For anything else, it would be hard to define what to review.)

    Other than that, I mostly use comments within my functions to document the logical and algebraical steps I took to arrive at the formulas I’ve encoded. The problems these functions solve are typically non-standard problems that required a significant amount of work until I could come up with the final formulas. So it makes sense to document the mathematical foundation, in case there is a change request or a bug creeps up in some odd corner-case. No amount of clever naming scheme or code refactoring could make up for that.

    When the mathematics is not so complex, I limit the comments to just describing the relevant steps. It’s true that even these comments may become outdated, but I’ve found since they’re not closely tied to the code, they tend to remain accurate until it’s time for a refactoring.

    That said, I often spend a lot of time analyzing an uncommented function to find out what, exactly, it does, beyond the rather vague description of it’s purpose found in the header. Once I understand the purpose of one section, I add a comment to document my findings, even though I’m aware that it might get outdated very soon, since the reason for my analysis typically requires me to implement some change. But even if I’m removing that comment the next day, it will still be useful as an information that is available in the version history in case I later come to investigate why I did this change!

    So, in summary, my experience with comments is that if you use them wisely, they remain useful in the long run.

Leave a Reply

Your email address will not be published. Required fields are marked *