Is There a Correct Way to Comment Your Code?
Editorial note: I originally wrote this post for the NDepend blog. You can check out the original here, at their site. While you’re there, take a look at all of the visualizations and metrics that you can get about your codebase.
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.
Things 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.
//Returns x + y or, if x or y is less than zero, throws an exception public int Add(int x, int y) { return x + y; }
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.
Something that appears to be missing, and which in my experience tends to be the most common reason for (useful) comments: even with supposedly perfect code, life frequently gets in the way, in the form of arcane business requirements, quirky third-party libraries or misbehaving external intregration components. In those cases, comments immensely improve maintainability.
To play devil’s advocate, don’t comments in those situations seem like spraying cologne on a smelly problem, rather than washing it? In other words, if I think of the problems of weird requirements, quirky libraries or buggy integrations, all of those have preferable solutions to just explaining the problem.
So I’d worry that getting in the habit of explaining the mess might get me out of the habit of fighting to clean it up. (Though I fully recognize that you can’t always win those larger battles)
I can’t count how many junior programmers have had their minds blown when I’ve made them go through the jQuery library and read the comments and code. There’s a lot of really good comments in there…
In my experience the most relevant comments follow that saying about why other implementations were not choosen.
And that’s when you’ve tried something that should have worked based upon your reading of the manual, but it doesn’t. Like you find if you pass a parameter a certain way to a third party API the whole thing crashes. So you create a work around, some kind of check, or manipulating the call… and you add a comment so someone coming along later realizes that this was done on purpose and doesn’t accidentally refactor it out.
I’d agree that explaining bizarre behavior forced on you by a third party API makes sense in order to avoid maintenance confusion. But I’d also (1) try not to use APIs like that and (2) if I did, I’d write a facade over them to hide the ugliness. Give the facade a descriptive enough name, and you might even be able to explain the problem with the code (though this may at times be quixotic, obviously)
My own professional challenge right now: my predecessors wrote ugly, bizarre facades over perfectly straightforward third party APIs. Not to worry, the files *using the facades* are heavily commented about how to use the strange new interface.
Yay comments! /s
lol… there’s no shortage of ways for programmers to confuse one another with their decisions 🙂
I think there is a big difference between one-line under 70 char comments and those multiline monsters. Any thoughts/styling guidance?
I guess more comment means more that could get out of sync with the code… but I don’t know that I’ve ever thought to differentiate much on the size of them. On the one hand, longer comments are probably more helpful in some senses due to being more descriptive. But on the other hand, every time I see a giant comment in some established codebase I think to myself, “oh, boy, this is going to be some awful code.”
I appreciate you playing Devil’s Advocate, Eric. It would be impossible for my comments to get out of sync with the code as they are everything from business rules to process description. As an example, a query with “filter out unused X because it causes Y” is still meaningful even if “X” becomes unfiltered. Striping it out if the rules change would be preferable, but even if left, it provides some insight in the future.
White space is free space. The compiler will strip them out, so the length should be according to what you need. I do not take pictures of my code, so functionality is all that matters.
//leaving a comment
=)
I think one situation where it makes sense to comment is when you have a good reason not to follow a established best pratice or convention. For instance, let’s say your team agrees that a try-catch with no code in the catch block should not be allowed (which I think is a sensible rule to have). But then it happens that in this particular case you have a legitimate reason to do this “wrong” thing. In this case, I think you should add a comment explaining why you had to do this; otherwise, you risk a colleague removing your try-catch… Read more »
Point taken, though my preference would be to enforce the behavior with a unit test. (Though I recognize we’re talking abstractly enough that someone could probably invent a case where this would be difficult or impossible to do)
More worms in the can? 🙂 Once we open the discussion to constraints/artifacts outside of the code file the conversation changes. In this case, why would we create this test? Because of a Design variation. While there are good arguments for including test cases in the definition of design, it doesn’t solve the problem, it just relocates it. Where in the test case does the rational go? …in a Comment? Design decisions go in design documents, the design itself can include code and tests, but those aren’t the entire design. I’m in favor of comment by reference – if you… Read more »
I sometimes conceptualize comment problems as a subset of stringly-typed problems. Comments can lie, error messages can lie, parameterized switch statements can lie, user prompts can lie, etc.
That’s an *excellent* way to think of it. Well said. I’ve never really conceived of it that way, but there is a lot of similarity to the maintenance headache of late binding schemes.
If you have to maintain code written by others you already have the answer! I have worked with code that was many years old, programmed by people who left the company and every meaningful comment was very much appreciated. Comment on what the code is trying to achieve in business terms. Why things are done the way they are done (also why certain implementations were not chosen). The example “//Returns x + y …” is pretty useless when I can see that there is a calculation that adds x and y. Documenting your code and keeping up to date doesn’t… Read more »
The example was an abbreviated hypothetical and not (I hope) an actual example of something you’d see. I mean, writing an Add() method in the first place would also be pretty useless. Something you’re saying here intrigues me. Have you encountered codebases where people would have “thrown them away” but for the code comments? I mean, usually legacy codebases stick around because the code is in production and used, in spite of efforts to migrate or sunset. Have you encountered a situation where the presence of code comments factored into the business decision as to whether or not to sunset… Read more »
I notice you said ‘ Why should I comment MY code’ – If you don’t you will be maintaining it forever !
Another good reason is Time, when you have been programming for 30+ years You wont remember why you did something in code – Its always useful to be able to re use an old algorithm or technique – or some weird interface spec.
Your old source listing is your documentation.
– Even if you re code it in one of todays here today, gone tomorrow languages , no one should have to reinvent the wheel.
My 2cents worth..
That’s really true for me. I’ve always put some comment pages just in front of my shared code adding to the bare code some kind of history changes, guidelines, samples, tricks, … Nobody comes to me asking: “Why?”, “How to?”, “Can I?”, … I think also that, as the length of a program increases the use of comments becomes more and more mandatory. In my opinion I have not to legitimize my code writing comments that explain why I have NOT done this or that. My code is my code and it is obviously different from code written by anyone… Read more »
I’d say however you find it effective to leave yourself context clues is what you should go with. I don’t, personally, find code comments helpful for that (I favor a lot of unit tests and discoverable APIs), but if you do, then, by all means, use them.
To me, commenting is self defense. I do not belong on either side of the religious war. I comment to help me maintain the code in the future. If half an hour of careful commenting saves me several hours of code reading when maintaining it, I win. As such, my comments rarely cover WHAT the code is doing, but rather WHY it was done that way and what the “gotchas” are. My assumption is that the code itself is self documenting, but the process is not.
That sounds like a pretty sensible approach to me. 🙂
1. Copy spesification into IDE
2. Comment text (add // before each line)
3. Start coding between comments
Frankly, that sounds like commodity programming where the developer is just a step away from being automated out of a job by a code generation tool. It makes me think of the 20 year old dream of writing code in UML.
I know that in some places this is supposed to be the correct procedure but only the most naive managers think that it can work and only the most cynical and depressed programmer is happy to work this way.
The code tells what. The comments tell why. If you have software developers writing code that will not be sufficiently thorough as to update existing comments when necessary, then either help them get to a professional level of performance, or get rid of them and hire developers who can perform in a professional manner. Some developers who think long term will use comments as a kind of pseudocode when initially developing the software inside the calluses they created. That allows them to think through what they are doing before writing code they will have to change. Leaving those comments in… Read more »
classes, not calluses. 🙂
As-is, it made for an interesting turn of phrase 🙂
I understand the sentiment (“stick to the group’s processes and procedures or get lost”), but this usually seems to lead to low morale shops dominated by whoever has the most seniority. In other words, developer X hires on and doesn’t find comments to be beneficial or helpful. The team “educates” him and he still doesn’t see it. You tell him to do it anyway or he’s fired. And, it’s probably not just comments, but a lengthy coding standards document, use of certain design patterns, tool preferences, etc. You wind up with a staff full of ‘professional’ people whose response to… Read more »
That approach is certainly a possibility (and I have seen that very thing happen) unless the team lead or software development manager doing the hiring addresses it during an interview, and has the communication skills to make the case. Not every experienced developer makes a good leader or manager.
Boy, ain’t that the truth. I’ve seen an awful lot of shops operate on the premise that the most tenured or skilled developer should naturally be tapped to manage the team. I never really understand why it’s assumed that the two skills strongly correlate.
This article has encouraged me to comment more.
“I think all parties can agree that commenting creates additional maintenance burden and seeks to pay for that burden with the clarity it provides.”
Uh, okay. Hours of coding versus seconds of commenting on the non-obvious aspects of the code. If you don’t like comments, don’t read them. If you don’t trust the comments, don’t believe them. If there are no comments, thank the previous programmer for your job security.
You spend “hours” coding up something “non-obvious” and you can then succinctly and satisfactorily explain that in “seconds?” That’s impressive.
If you cannot describe what you did, why you did it and how the next person should look at it, you are not professional yet.
If you have worked on some of this “self documenting code” and tried to maintain it, then you should know better.
It is like the engineer that uses math to explain how something he designed works. In many cases the math obscures some important points that he or she did not understand themselves, and the math shows the same as the function, but neither shows how to troubleshoot or fix a failing piece.
I don’t think anyone would dispute that being able to communicate your choices effectively is a valuable skill. (Though you seem to be making the “no true Scotsman” argument as some of the stack overflow participants did, which is that “if you don’t do it my way, then you’re not really a programmer.”) But why would the only way to do it be through the medium of inline code comments (as opposed to doing an external write-up, creating expressive automated tests, using code contracts, or, just doing a better job than what you’ve seen of writing “self-documenting code”)
As long as the external documentation is discoverable a year later by a new hire seeing the code for the first time. Inline comments or external – it makes no difference as long as it is usable short-term and long-term.
I definitely agree with that. It’s exactly what I’m driving at (and why I don’t use a ton of code comments, but I don’t begrudge that approach when teams find it effective).
You definately need a comment if your code does something that can easily be misinterpreted.
if(p = q) //assignment folllowed by test
without the comment it likely to get ‘corrected’ to
if(p == q)
which would break the code
Think about the history of how that comment got there in the first place. Someone writes “if(p = q)”. Then he realizes, “Oh! Someone might misinterpret the two-step assignment/test as a simple comparison…”. Which is a great realization. He now writes: if (p = q) //assignment folllowed by test or p = q; if (p) I’d rather he writes the latter. Because then more thoughts can continue flowing: “wait, I’m doing an assignment and I’m conditionally doing something based on a value. But prior to the assignment, I had all the information necessary to know which conditional branch I was… Read more »
Wow, very well said! I was planning to respond in a similar vein of thinking, but you expressed that as well as I could possibly have.
Code comments should be added wherever the code might otherwise be misunderstood. Apart from that the most useful thing is a seperate document which is a narrative written in readable prose describing major design decisions and subsequent major design changes or refactorings. The main problem with reading and working with the code of others is complete disorientation.
This is all very theoretical. The acid test is code maintainability and that would require a study testing which structures, formats and styles of code are in actuality the most efficiently maintainable. Also, comments can have other key roles, such as the ‘special’ format of comments used by JavaDoc in NetBeans to describe the use of functions in the Intellisense – absolutely indispensable.
Definitely agreed about the style of comments you mention (though in my mental model, I categorize that as something else, namely “code documentation”).
As a lifetime consultant, I feel that comments are my billboard that highlight my work and can lead to future business.. Precisely explaining delivered code is important. Quick reference to specific areas of concern aid in understanding much like the TOC in a book that we evaluate for purchase or reference. Admittedly, most code nowadays is short but if commenting is avoided what about the technical documentation??
For programmers whose native language is something other than English (more seriously, not Indo-Europian one), comments written in their native language can be much more helpful, since their code is inevitably littered with ‘wrong’ variable and function names. Simply it’s hard to communicate only with the code itself – like communicating with a foreign language.
I’m currently tweaking a WordPress plugin, and if the original developer hadn’t added comments along the way I’d seriously consider hanging myself. He added a lot of really good comments, and I thoroughly appreciate it.
When someone new wants to step in and quickly change some code, comments can make it so much easier than digging through code to understand it. In this situation, I don’t need or want to understand the code–I just want to find where to make the necessary updates so I can move on with my day.
I think it’s funny how many COMMENTS have been added to this article. 🙂