Nov
12
2012

Comment your damn code

I'm just going to come right out and say it:

Comment your damn code.

 

Every now and then I run into an engineer--sometimes pretty high level--who thinks that you don't need to comment code. I'm going to call bullshit on this. I've been doing this a long time. Chances are, way longer than you. We are right in the middle of coding our asses off trying to launch something awesome, yet we still comment practically everything. There's no excuse not to. Every 3 to 7 lines of code you'll find some amount of editorializing. Maybe every few hundred lines you'll find a good joke too.

Where the errors are

Look, there is what you intend and what you write. Your bugs are in between the two. When you write comments you are telling me what you meant to do. You code is telling me what you did. Either the flaw is in what you intended to do or, if your intent was correct, then it's in your code. Help me know which is which.

Don't be lazy

A common argument that I hear is that comments will get out of date because code will be updated but comments won't be. Are you not updating comments? Your coworkers? Stop being lazy and stop settling for a culture where it's okay to be lazy. Communicate how you work and let other people know that you'd like the same courtesy. Not commenting because someone, somewhere, in the future might do you wrong is just looking for excuses.

You're a Journeyman

Gender neutral of course, but you're a Journeyman. As such you have an obligation to teach others that are still learning. Your comments coach the Youngling who is reading your code. Tell them why you choose to use a Tuple in this case, but not the other (bonus points for links to stack overflow or dotnetperls ... you know you can do that in your comments, right?) What are you taking a shortcut here? If you're not taking shortcuts, then you're not shipping so you better tell the Youngling what was special about this case. Otherwise you'll end up with all of the wrong copy and pasted code everywhere. Look! Now your crappy code is a company pattern! No comments and all!

You can type

Part of my hiring process is whiteboard coding and keyboard coding. All good coders are touch typists. So you type 40 - 60 wpm. So then tell me again why aren't you writing comments while you blaze through your code? Because clearly the 30 seconds that you take now to tell me about what is going on in this icky mess that the biz dev guy had to have done this week to get a nice $75k this month needs to ship. But what are we going to do next month. Can we rip it out? Or is this code locked in stone. I know what the code says. But tell me the intent.

You're going to get old

I told you. I've been doing this for a while, probably before you entered middle school. I'm still slinging code and I still love it. And one day you'll be old like me too. And if you're like me (and I'm not an intellectual slouch mind you) the day will come when you know too many layers, too many abstractions, too many stacks that you can't remember it all, all of the time. Your code comments will guide you. They'll remind you that six months ago you did things this way, with this pattern and that it was pure awesomesause. And if you're really good--and still evolving as a coder--you'll realize that this code was crap and now you'd do it a completely different way. But you'd still have your comments to remind your own damn self what you were thinking and why. And you won't be so much as old as experienced, growing, and knowing where you were six months ago before you knew any better.

So comment your damn code. 

Comments (22) -

John Sonmez

Better to write expressive code that is well named.
I've hardly seen a pieces of well written code that needed comments.

elegantcode.com/.../

Almost everywhere there is a comment it cab be replaced by well named variables and methods that communicate the same point.

ImThinking...Superfluous

Amen

Darren Cauthon

What are your thoughts on idea of making readable code, even to the point of refactoring the code into small methods with very descriptive names?  

Roland

You make a good point that comments help to make your intent more clear, while the code itself just explains what the program does. Very good reason to have some comments here and there.

However, I agree with the "high-level engineer" who says you don't need to comment code. Instead I say test your damn code! Testing brings all the benefits of commenting and more:

Tests help document and clarify your intent. They convey your assumptions, expectations, and show you exactly how methods are expected to behave when you run the test.

3 months later when you're adding new features, a failing test tells you that you introduced a bug before you ever run the new code.

That said, comments have a place in the tests themselves. Much better than scattering comments all around the code base.

The other place for comments is in the version control. Make small, frequent commits and set up your version control so that it forces you to comment each time.

When you're doing these things, comments in the code just start to look redundant and noisy.

I'd rather see some tests that spell out the intended behaviors than a bunch of comments

Justin Koreska


Comments are a crutch for unreadable code.

With comments every 3 LoC - I can't even see the code from the comments!

You should be describing your intent with tests, class and method and variable names, separation of concerns, and readable code! Take that clever 1-liner and break it into sensible lines of code with descriptive variables. Or, take that monster function and break it into sensible methods with meaningful names. Then, the intent will be clear and your comment will be redundant.

Now, I've been slinging code a long time, too, and I'm getting old. I know sometimes you have to comment that crappy code so you can ship and refactor it later and later never comes. That's fine, use the crutch in those cases, but it's no substitute for readable code!

Dan Esparza

Damn straight.  One grumpy young man to another (I've been doing this 20 years, myself) this is a good message.  

Please comment your damn code.

Chris Patti

Really love this article!

I'm in kind of an odd 'stuck in the middle' position.  I'm a release engineer, and as such I end up working on large bodies of code around deployment.

Deployment is the seedy back alley of the development world, it's the un-sexy work developers do when their hand is forced (generally speaking).

I would *KILL* for a nice block of well commented code to maintain Smile

Nathan Alden, Sr.

Hey author, how about refactoring and abiding by SOLID principles? That does more than any massive block of commented code could ever do.

I find comments to be rarely useful. Most of the time, I comment code that solves a domain-specific problem, such as the parsing of If-* headers according to the HTTP 1.1 specification, or perhaps how an interest rate calculation words. Mundane, boilerplate code--of which there tends to be a lot of--isn't worth commenting.

http://projects.nathanalden.com/JuniorRoute

jbright

I am in a rush at the moment, so I'll post more later.

Absolutely you should try to write code that is easy to read. I agree 100%. But many (most?) of the time people assume that the next person picking up the code is as senior as you, the author. Typically that's not the case. Make it readable and explain the "whys" (and often the whys are business reasons, not technical).

name

Give us some examples.

Lucas Theisen

Comments are like sentences (sequences of words ending in a period) which try to convey (tell you) more information (discrete nuggets of knowledge) that should easily be deduced (reached a conclusion using logic) from the encompassing context (information surrounding the sentence) through the use of rhetorical parenthesis (en.wikipedia.org/wiki/Parenthesis_%28rhetoric%29).  Annoying...  I know!

Tim

(sorry to use this tone btw, but I am mirroring the tone of your article)

Look, there is what you intend and what you write. Your bugs are in between the two. When you write comments you are telling me what you meant to do. You code is telling me what you did. Either the flaw is in what you intended to do or, if your intent was correct, then it's in your code. Help me know which is which.

You are confusing commenting with specification. The specification tells me what I intended to do, the code implements it. There are many ways to specify things; some of them are automatically checkable (e.g. full program specification + verification, or unit tests, or many other ways). Comments are not automatically checkable, they are imprecise and hard to manipulate with tools (e.g. refactoring tools) - in my opinion and experience only people that have not yet learned how to properly specify a program say things like you have about comments.

Oh, and also it quite possible to have a bug in your specification (your intent) - this is in the gap between what you intend and what the customer actually wanted. So having a spec (at the most abstract level) that your customer can read and can also be automatically checked is a very powerful thing indeed.

Not commenting because someone, somewhere, in the future might do you wrong is just looking for excuses.

That misses the point entierly. The point is that we want to be efficient when writing programs, and there are better (lower cost, higher return) ways of getting the same result than commenting. For example having highly readable code, and a comprehensive executable specification (which forms an executable/checkable documentation at multiple levels of abstraction if done properly) is /much/ better than commenting - it does everything a comment does, and it is automatically checkable and you can run tools over it and it is precise and it doesn't take any longer to do well (poor comments are quicker, but good comments are at least as hard to write and maintain as proper specifications in my experience).

Heck, if we use good enough tools (cucumber, fit, etc) we can even make the acceptance documentation executable and checkable. Even the performance (and other non-functional properties) can be specified and checked in this way if you really put in the effort.

Commenting is unnessarily expensive; it can be replaced by other techniques that are almost completely better and also almost always cost less over time. I think there are, very, very few circumstances were writing a comment within the code is appropriate (it is typically a sign of a programmer who is not in control of their program). Typically when I have worked with or managed programmers who have resorted to writing comments I have found it to be an indication that they did not know about a technique that they could use to properly specify or otherwise simplify their code so as to remove the need for the comment.

So, people in the future /won't/ maintain your comments - because they know that your comments are a waste of time. They will resent having their time wasted by having to read your comments, and sort out the ones that are "teaching" them how to code from the ones that are actually useful for the task at hand. They will be cussing you for writing code that needs so many comments; they will be cussing you for having to wade through and maintain stuff where you are trying to "teach" them things that they already know, or teach them things that are now hopelessly out of date (if your code is good enough to be still around after that long, that is); they will be cussing you for making it harder to use their tools when they have to manually go and move your comments or fix them after an automated refactoring, and they will be cussing you for wasting all that time writing and maintaining comments when you could (should) have been writing and improving your proper detailed+executable specifications.

Oh, and by the way, try to write your code well enough in the first place so you don't have to make an icky mess when a deadline hits.

So, please, remove your damm junk comments and write proper executable documentation (specifications).

Nate

If you don't think you need comments, chances are, you're thinking too much about dumb comments. There's no need to comment simple accessors or really any boilerplate code that should be obvious to even a newbie.  However, there are plenty of places where comments make your code way more maintainable.

Tests are all well and good. They can explain what the expected outcome is, and how to use the code, but the inner workings of the code can't and shouldn't be exposed to the outside, and therefore can't and shouldn't be explained by tests.

There's three things you should put in comments.
#1 - WHY you're doing something. WHAT you're doing is hopefully obvious from the well-written code everyone else has commented about.
  But WHY you're writing the code isn't always obvious. Why are you stripping off the last two characters of that string? Why are you making a copy of the array rather than just using the original? Why are you acquiring the locks in this particular order?
  This is the type of information you can't possibly put into variable names or function names. Or if you did, your code would be completely unreadable.

#2 - Coding notes for anyone else who might work on the code. For example, I often write comments warning future programmers about potential problems that they might not think of if they edit this particular code. This is quite similar to #1, where you note why you did (or did not) write some particular code, and how to maintain the code without breaking anything. Tests can tell you something is broken, but they can't always tell you why it broke.

#3 - WHAT your code is doing. This should be very rare, but occasionally, for performance reasons, or while interacting with code you didn't write, you have to do some backflips in the code to get things to work right. This kind of obscure and arcane code comes up in nearly every job. This is a time to break from tradition and comment on what exactly the code is doing (and likely also why it needs to be done this way). Yes, it means you'll need to keep the comment up to date with the code... but with this type of code, you often need the comment to remind you exactly what the code is doing anyway.

jbright

Great comments BTW. And I definitely don't mind the tone matching my rant.

Just browse any number of projects on github. There's some really good stuff, not so good stuff, and crap. Inevitably the really good stuff is both well written and well commented. I don't think I could say it any better than Nate did above. Hey, I really love all of the work that Miguel de Icaza has done and we use Xamarin to build the iPhone app. But if the earlier code examples for MonoTouch had say 15% more comments in the examples, I would have picked up on the intended pattern much, much quicker. (Still, in many cases the examples were much better than Apple provided!)

Not to mention that if you're a full stack developer chances are you're not a expert in every layer in the stack. You need cues from comments. Or maybe you just can't write code like John prescribes because you're in javascript land. I'd love to see more comments when I see this:

.children('ul').click(function (event) {
           if (event.stopPropagation) { event.stopPropagation(); } event.cancelBubble = true;
       })

WTH? Why? Random (but real) example.

You're going to READ code 100x more often than you WRITE it, including refactoring. Just like you use a Cliffs Notes or similar when reading Shakespeare, having a guide when you are reading code helps tremendously.

David T. Macknet

I agree wholeheartedly with the rant, and also find some interest in the comments ... particularly in those who believe that good testing will somehow magically generate good code, or repeatability, or provide any of the other benefits of commenting.

I've been coding for around 20 years, full-time (at least, being paid for doing so).  I've never found a comment that stood out as garbage, at least, not that I can recall.  Mostly, I've found code where it was obvious that the developer was trying to do something, but so help me, I couldn't determine just what.

Another good reason for comments is when things break with the expected pattern (say, because a library's implementation is counter-intuitive, or where that library has a fatal but difficult-to-find defect).  Those places are where I find myself commenting the heaviest: if it's taken me a week to find out that there was a problem in a third-party code library, I certainly want to put some expletives around the work-around, so that 1) I don't have to do the same problem-solving again (or can remember what I did), and 2) so that some newbie doesn't encounter the code and "fix" it.

Sad to say, some people just don't like to read comments.  I had a manager who insisted that they be removed before release to the client.  Needless to say, I don't work for that person any longer, and that company's projects frequently fail.

Tim

will somehow magically generate good code, or repeatability, or provide any of the other benefits of commenting

Hopefully not too many people think that this will happen by magic! In my experience it is quite a specific process that produces both good code and matching good specifications (tests, etc). I can certainly see how programmers that were not able to follow such an engineering process or had difficulty applying the self disipline (or lacked the tools, training, support, etc) necessary to produce good code could lead themselves to believe that extensive commenting was good practice (and in this situation it is probably better than no commenting).

I've never found a comment that stood out as garbage, at least, not that I can recall.

I have unfortunately seen quite a few. Where does this leave us? Usually I have seen comments left by programmers that thought that what they were doing was really difficult, but actually had simply not understood the problem correctly and had no concept of a reasonable algorithm to solve the misunderstood problem. The comments I see are generally just as confused as the code they are commenting. Complicated code, complicated comments. Or to put it another way, why would I expect a programmer who cannot write clear well specified code, to be able to write clear well specified comments? And if the code is clear, I have seen very few comments that added value.

Those places are where I find myself commenting the heaviest: if it's taken me a week to find out that there was a problem in a third-party code library

This is somewhere I have also used comments myself. Typically to document where the behaviour of a library differs from either its specification (bug), or is insufficently specified and counter-intuitive. In my experience, however, this is very rare compared to the total amount of code I have written and hardly comes under the general category "comment your code" - more "comment extraordinary circumstances". Actually, more often I have come across confusing and confused comments made by programmers that have not understood the library and subsequently made a usage error. The content of the comments are typically useless (because of the confusion); although the presence of comments in code can act as a warning sign that the programmer was confused.

Why are you making a copy of the array rather than just using the original

copy the array in a method that is named after why you need a copy? Even better, if your language has types and encapsulation (e.g an OO language) use them (wrap and encapsulate your raw arrays).

This kind of obscure and arcane code comes up in nearly every job.

If you absolutely cannot document it with tests (including performance tests - and if it is performance critical you should be testing its performance), others kinds of specification, code style techniques, etc. then you could put in comments - but I have typically found that the number of cases where I have to do something like this have been quite rare and the number of times I could not communicate it by some other (exact) means even rarer. I have worked quite a bit on performance critical code. I prefer to use well known algorithms and data structures where possible, and use technical names. I don't want to troll, but have you considered that it might be your own skills that are leading you to write at least some "obscure and arcane code" on nearly every job that you do?

Nate

document it with tests

As I said before, the specific implementation cannot and should not be documented with tests. Tests document *what* the code does. They cannot document *how* the code does it, or why it does it.

I can write a method that does the same thing in 100 different ways. The tests for that code would all look identical. The tests can't tell you why I chose one way over another. That's what comments are for.

copy the array in a method that is named after why you need a copy

So... instead of this:

// copy the array so we keep the original pristine in case we have
// to roll back our changes due to a later error
copy = cloneArray(original)

you want me to do this?

copy = makeCopySoWeCanRollBackLater(original)

and then make a method with that name that just calls cloneArray?  That makes the code clearer?

have you considered that it might be your own skills that are leading you to write at least some "obscure and arcane code" on nearly every job that you do?

Do you not ever interact with wacky APIs from the OS, third party libraries, or just plain mediocre code from other individuals in the same company?

Here's an example of actual comments I've written at work to explain why in the hell I'm doing something:

// don't use double.parse, since that is locale-specific
// and this format is always static
-- fixing a bug by using a regex where we had been using a built-in parser that failed in non-US locales --

// this causes Word to set the extension appropriately according
// to its default save format
-- explaining why we're removing the extension from a filename --

// remove the current user from the list, since the server automatically
// adds the current user anyway
-- explaining a fix to a bug where the current user would be in a list twice... technically the server should handle it, but it's not fixable on the server without a huge rewrite --

// this just means the file doesn't exist, which is
// fine, so we can ignore it
-- explaining an obscure exception error code, and why it's ok to swallow it --

I really don't understand how people think they can write readable, maintainable code without comments. You may understand your code today, but you probably won't in 6 months, and someone else certainly won't. Unless your code is all boilerplate and doing the simplest things imaginable, somewhere there's going to be complexity, and you'll need to explain yourself in plain text, not in code.  if you try to shoehorn these explanations into variable and function names, you'll often end up making your code *less* readable, not more readable.

I understand that the world is not simple or perfect, and that anywhere there is imperfection or complexity, there is the chance for misunderstanding and error. Comments help convey the knowledge of the current programmer to future programmers working on the same code (even if that future programmer is actually the same person).

Development is 10% creation and 90% maintenance. Comments make maintenance easier. Why avoid them? Do all those other things too, but don't think the lowly comment is beneath you just because it doesn't come with a framework, toolset, or have a fancy name.

Tim

Nate - don't read this if you don't want to read me critisising your approach to programming. You probably have better things to be getting on with! I have, however, heard all the arguments you are making before, I have worked with programmers who swore by the approach you are suggesting - but eventually found they had no need for it after learning the better, more modern techniques that I in turn have learned from some very excellent programmers. On to my point:


Tests document *what* the code does.

They specify the meaning of the code.

They cannot document *how* the code does it

The code documents how it does what it does.

or why it does it.

Yes they can. I automate almost all my acceptance tests and create them in domain language that describes exactly and specifically the user or technical requirment that drives each feature.

you want me to do this?

copy = makeCopySoWeCanRollBackLater(original)


Sure, if you can't think of a better way of doing it. The fact that you have suggested this solution is kind of confirming my point that programmers use comments when they lack the techniques required to do something better than using comments. I imagine that I would encapsulate the array in an object which has methods something like "startTransaction" and "rollbackTransaction" (or generally something more domain specific, as I would actually know what the array was for if I was doing this for real). Your lack of familiarlity with the ways that complex program behaviours can be encapsulated, abstracted and named is probably the reason you need to use comments.


// don't use double.parse, since that is locale-specific
// and this format is always static


I'm guessing what the code is doing a little, but I'm probably going to create a class/type that encapculates this number parsing logic. The type is going to be used every-where this sepecially formated number is used within the program. I'm going it write a bunch of tests that check that this class does the parsing correctly - there will be some tests that make sure that the parsing is not being done in a locale specific manner. If someone accidentally changes the implementation to be locale specific those tests are gonna fail. This is /way/ more robust and maintainable than writing a comment and using raw primitives.


-- fixing a bug by using a regex where we had been using a built-in parser that failed in non-US locales --

I'm going to write regression (unit) tests that check that the parser works in non-us locales. If someone changes it back accidentally or the tests will immediately fail. They probably won't make that mistake however however, because they will have looked at the test cases before they change the class, and they will have seen one called "testParsingWorksInNonUsLocales". The reason that they will have looked at the tests cases is that they are doing TDD, so will always be writing a test before changing code behavior. If they however are careless or lazy and don't look at the tests - then no harm done, the tests will fail durring the CI build and the error will be caught.

this causes Word to set the extension appropriately according to its default save format

I going to create a type that encapsulates the file name; I'm not passing around filename as a string, or as a "File" or whatever 2rd party type you have available. I'm going to write an integration test that verifies that what you are saying is true. the test will be called "testThatWordSetsTheExtensionAppropriatelyAccordingToItsDefaultSaveFormat". Its OK to have long test names, as they are never called from code. (only called automatically by the unit testing frame work). I am going to explicitly check, and any programmer that makes a mistake a violates this will be immediately told about it by the test failure (in the CI server if not locally). However - someone that misses, or misunderstands your comment is in big trouble.

remove the current user from the list, since the server automatically adds the current user anyway

Same as above. I'm going to write an integration test that forces the program to have this beahviour. I sometimes include the issue tracking number in the test name: testUserIsNotAddedTwiceByTheServer_12543(), I might also abstract the part of the code that removes the user in a procedure called "preventDuplicateUserAddition()"

this just means the file doesn't exist, which is fine, so we can ignore it -- explaining an obscure exception error code

I am going to encapsulate the error code (I assume it is a primitive or 3rd party type that you cannot change). I'm going to have a method that is "errorCode.isFileDoesNotExist()" or if for some reason I cannot do that I am going to have isFileDoesNotExist(errorCode) in my conditional.


So, essentially, I think that none of the comments you have suggested are appropriate places to have comments. I have come across many programmers who write comments like this. In my experience their code is not particularly well decomposed because they lack the techiniques of abstraction, encapsulation and specification that allows them to write simple, clean, understandable code.


don't think the lowly comment is beneath you

Far from it. I argue that the comment is harmful when put alongside modern programming techniques. I don't think it does what you claim for it, at least it does it nowhere near as well as the other techiniques that you could use. And, if you use those techniques then almost all comments become mear duplication and are redundant.

In short: comments are fine if you don't know any better, but when you do learn better they are pointless at best. If you are stuck in a situation where you can't do it right (where you lack tools, or support from the person paying you, or whatever), then comments are a substitute that you can fall back on, but that is all they are.

Tim

You should try to avoid writing comments. This doesn't mean: "don't write a comment where it is needed" it means "make the comment not needed". If you really can't make it not needed, then you should put in the comment. The comment is better than nothing, but its not better than doing it in a way that does not need a comment.

I mean, appreciate that needing to writing comments is a sign that there is something unclear about your code/specification. And try to, over time, work to learn how you can eliminate them.

Tim

Also, don't forget about assertions. You can often add checkable assertions to your code if you /really/ need to. e.g.

assert errorCode == FILE_NOT_EXISTS

This is way better than a comment, although is not as good as writing code that doesn't need the assertion. i.e. try to structure the code so that the condition is avoided, but if you can't then document it using an assertion. At least they can be checked, and are likely to be refactored correctly by tools.

So:
    checkable specifications (tests, etc) and clean code are the best
    then assertions if you really can't think of a way to clean up your code
    then comments if you really can't do either of the above

Try to learn from each situation where you end up having to comment and think "how could I do this better?"

Mike

I've been coding professionally for over thirty years, and find this trend away from commenting to be extremely ill-conceived.  Of course you should write code that is easy to read, of course you should do all of the other things cited as reasons why commenting shouldn't be necessary, but you should still comment. As pointed out by the author, commenting tells me what your intent was, while the code only tells me what you actually did. Not commenting is like entering into a business deal without a contract- the contract is there to record your intentions, and can be used as a reference to bring behavior back in to alignment and prevent things from falling apart. Everyone should act like contracts are not necessary, but in reality they are.

In thirty years I have never seen a program and said, "Wow, there are really too many comments here. I wish they hadn't done this." But several times I've used comments to find and correct errors.

Professionals comment their damn code.

Carl

I think comment should tell others what you are doing instead how are you doing.
Of course, some thing about how you are doing if nessary is good,
but do not write so much like this.
Most programmers are impatient about others code.
And in most situations, it would be enough, readers can easily understand your code if he/she knows what you are doing.

Pingbacks and trackbacks (1)+

Comments are closed

About CollectedTech

Hi. We're building something new. We're ambitious. We're not afraid. It's not the first time that we've launched something completely new, but this time we thought we've opensource our thought process. We expect to make mistakes. Maybe you'll learn something from what we do right and from what we do wrong (we sure hope to). 

We're relatively technology agnostic, but are fluent with .net technology so we usually start there. Start with what you know. Technology itself rarely makes the different in a successful startup. We incorporate whatever we can to solve the problem. 

The Bloggers

James Bright

James Bright, techapreneur, is a 18 year veteran of the IT world, and has the battle scars to prove it. 

Christian Heinzmann

Christian Heinzmann, (Computer|Beer) Geek Dad - @sirchristian

Month List