Settings

Theme

I hate comments

timothyfitz.com

29 points by commanda 13 years ago · 54 comments

Reader

randomdrake 13 years ago

Hopefully no one even moderately unfamiliar with the language the code is written in needs to find out how to fix something that is broken. Citing breaking code by using some global that makes the comment no longer true? Sounds like an abuse of globals or someone not cleaning up the comments, not the comments themselves.

So many times I have had to repair code in languages I wasn't quite familiar in or that was simply using methods I hadn't learned yet. Those comments were life saving.

Comments describing intentions of code also allow for someone to come by later and quickly and concisely understand what the code was doing and where it was going.

I cannot think of a single instance where parsing 65 lines of a function definition was ever quicker than reading:

This method takes a foo object, applies HTML encoding, and returns an array of the original and the clean code.

In the same vein, saying that Unit Tests are a replacement for comments just brings me back to my original assertion: I already am looking for help understanding the code base, so I should look at more code elsewhere and parse another long list of assertions?

Bad comments are bad like bad code is bad, or like bad pie is bad. But comments, code and pie aren't bad.

Please don't stop commenting your code because you feel like you can be more clever with the language instead. Someone may be much more familiar with the language the comments are written in. They may may need to do something with what you wrote.

Whenever I read some new reason why comments aren't cool or why some programmer has decided they[1] can just be clever with the language, I can't help but think they just don't have enough experience to know why and how comments can be absolutely necessary and fantastic.

[1] not saying this is necessarily true in this case, it's just the impression I get.

  • grn 13 years ago

    Comments are useful when they provide information that is not in the code (e.g. rationale for the choice of an algorithm, source of a regular expression that parses an URL). Your example HTML encoding function can be coded as:

        def clean(foo)
            return [foo, foo.apply_html_encoding]
        end
    
    The encoding logic should be contained in apply_html_encoding. The point is that most of the functions/methods that are 65 lines long are badly coded.
  • TimothyFitz 13 years ago

    "This method takes a foo object, applies HTML encoding, and returns an array of the original and the clean code." could be a 3-line unit test that's just as clear to read, but has the side effect of actually being true instead of maybe being true!

    I would consider that comment just as bad as the ones in my examples, but maybe not quite as obviously so.

    • makmanalp 13 years ago

      The main benefit of comments that you seem to be missing is that they are in the right context. Unit tests, while useful and required, make for boring reading and are not right where you need them. If I need to open up a separate file and scroll through tons of other tests to find the unit test "docs" on a function, you've lost me already.

    • randomdrake 13 years ago

      Of course a better comment could be written. I was using a short and concise comment to illustrate how you can gain a huge amount of understanding in a single line versus parsing a long function definition. Other comments here make suggestions for writing good comments.

    • endgame 13 years ago

      > could be a 3-line unit test that's just as clear to read, but has the side effect of actually being true instead of maybe being true!

      It also has the side effect of being in a different file to the one you're trying to read.

    • makmanalp 13 years ago

      Hey, actually, I think I found exactly what you want, maybe!

      http://docs.python.org/2/library/doctest.html

  • timwiseman 13 years ago

    I prefer to lean towards overcommenting, and I prefer that developers whose code I will have to work with later do the same.

    But as you say, they need to be good comments, and comments that either describe intention or explain something in the language that might be rather obscure can be very useful.

  • alexchamberlain 13 years ago

    Is that really quicker than reading return array(foo, foo->encodeHTML())?

Pewpewarrows 13 years ago

Sounds like the developers who wrote that code didn't know how to write comments. Here's some guidelines:

* Anything that duplicates the line they describe in prose should absolutely be removed. They're worthless and become out of date immediately.

* If you have logical "paragraphs" of code separated by newlines and comments summarizing the paragraph, that's a great indication that your parent method/function/whatever is in charge of doing too much. Turn the comments into names of new methods/functions and refactor accordingly.

* If the algorithm is sufficiently complicated, it definitely deserves a documentation block describing the "how"s and "what"s. But more often than not those comments are just a duplication, as specified in the first bullet point above. If you don't think any code ever deserves these sorts of comments: congratulations, you've never worked on anything non-trivial in your career. I suggest that you find more of a challenging project.

* Definitely leave a comment behind explaining the "why"s behind a particular block of code if its intentions are not immediately obvious.

* Definitely have headers of documenting comments for functions/classes/methods/parameters/etc. Is your first reply when someone asks "How do I learn to use Rails?" to say "Read the entire source code to Rails"? No, of course not. For the same reason, your reaction to "How do I use this block of code" should not be "Read the block of code." Abstractions and proper APIs people, come on. I should be able to glance at the docs above it along with the definition and know how to use it, what to pass to it, and what I might expect in terms of returns / side effects. Bonus points if you have a tool to auto-extract these into a static site that you host for your team.

kjackson2012 13 years ago

What a terrible and self-righteous post.

How is a test case supposed to explain why MAX_COUNTER is set to 5 or 20? Comments are the single-most important thing when writing code, in my opinion. When feature specs are lost, and documentation goes out of the date, you only have code. And if you're supposed to jump through hoops like test case code to try to divine WHY things are as they are, then you're dealing with really hard-to-maintain code.

I strongly suggest all developers to ignore this blog post, and to comment as best as you can.

  • katbyte 13 years ago

    > I strongly suggest all developers to ignore this blog post, and to comment as best as you can.

    Bad or to many comments are better then no comments. Its not exactly hard to remove them, their absence will never break the build unlike not understanding the implementation!

    • Ives 13 years ago

      That's not exactly true, if the comments and the code have at some point diverged, the comments can only serve to confuse the reader.

commandaOP 13 years ago

I helped the author edit this post for clarity, but it took all I had not to argue with him because I strongly disagree with his thesis. My main language (Objective-C) is relatively less readable (compared to his main language of Python), and I would absolutely not be able to function in a team, or even with code I'd written myself over a week ago, without heavy commenting. I do believe he's right though with respect to test coverage being effectively a runnable comment or explanation of how a particular module works. However, to me at least, tests are no more readable than the source code itself, so I still rely (and implore my teammates to rely) on heavily commenting their code. Especially when dealing with inscrutable things like OpenGL code.

  • potatolicious 13 years ago

    Not to mention code is imperfect. My main platform is Obj-C/iOS and there are numerous API bugs, workarounds, and bits of ugliness involved when integrating with third-party APIs and libraries. These definitely involve comments because they are incantations that have a reason for existing, where the reason is entirely non-obvious on examination.

    God help the guy who rips out a seemingly innocuous line of code only to subtly break things underneath. Even a simple:

        // Hack around time parsing bug in iOS3+, see [StackOverflow thread]
    
    saves hours of lost productivity.

    We can get rid of comments the moment we invent a perfectly expressive language, where every single line of code in your entire stack is under your control and everything works exactly as advertised out of the box.

    Until then, I'll keep commenting where I need to, and never when I don't.

sankyo 13 years ago

The comments that he shows are pretty worthless. However, comments are often necessary to explain WHY we are doing something.

oven.setTemp(350) // 400 will burn them, 300 they will be mushy

fluxCapacitor.setOption(THRESHOLD, 1.21E9) // lower thresholds will prevent return from time travel. Please see http://en.wikipedia.org/wiki/DeLorean_time_machine to review the physics

  • kondro 13 years ago

    Both these are fixed by method extraction though.

      function setTemperatureToCookPerfectly() {
        oven.setTemp(350);
      }
    
      function ensureReturnFromTimeTravelPossible() {
        fluxCapacitor.setOption(THRESHOLD, 1.21E9)
      }
    
    Now wherever you see these lines in your code, you know exactly what they are for.

    To quote one of the Ruby Rogues, "A comment is a lie waiting to happen."

    • katbyte 13 years ago

      In both those examples information about why the variable needs to be set to that specific value is lost. At some point the variable needs to be set and the more information on why it needs to be set to a particular value the better. You can't pack all the required information into a function name and i would dare say you shouldn't.

      Granted I would personally do:

          const int perfecttemperature = 350; // 400 will burn them, 300 they will be mushy
          .....
          oven.setTemp(brownie.perfecttemperature);
      
      but still comment it as to why i picked 350. Comments are for the why, and the why is the most thing to understand.
    • talmand 13 years ago

      Wouldn't that function name have to be more like setTemperatureTo350ToCookPerfectly400WillBurn300WillMush to match what the comment is saying?

      What if later it is determined that the proper temperature should instead be 375 because at 350 they aren't quite cooked enough?

      • kondro 13 years ago

        And what would happen in the original?

        People have a tendency to believe what the comment says, even when the code says something completely different.

        It's easy to say that you would update both the comment and the value at the same time. But I've seen mismatched comments in code all the time for even a contrived example like this. And then what do you believe? Is the comment right with an incorrect implementation, or is the implementation right with an incorrect comment?

        • NateDad 13 years ago

          Never replicate the code in the comment, then the comment won't be lying when the code changes.

          This is a poor example to work off of. You'd probably have something like RECIPE_TEMPERATURE = 350, which you could then tweak to 375 if you needed to...

          A more effective example would be

          oven.Temp = RECIPE_TEMPERATURE

          // we have to wait for the oven to preheat

          thread.sleep(time.Minutes * 5)

          oven.contents += cookies

          Could you make that second line of code into a function preheatOven()? Sure. And your code would be less readable, because you have to break context to go see what the function does... only to find it's one stupid line.

          Method names are not comments. They are hints at what the code does. They should not explain why the code is doing it (because the why almost always requires a lot more space than you can fit into a reasonably sized method name).

    • shrub 13 years ago

      Until you change what those functions do, and then the function name lies.

B-Con 13 years ago

I personally have four reasons for writing comments. If a comment does not fall squarely into one of them, I try to omit it:

1) Why the code is doing what it's doing. What's the motivation? Why is a check necessary? What's the context?

2) High-level overview. 20 lines of code may speak for themselves, but a quick sentence can easily summarize it. I love well-summarized code. "Do X with the Y unless it's Z" is a really fast read. (Function names obviously provide this sort of explanation, but sometimes a name is not obviously not always sufficient.)

3) Stubs / future notes. Sometimes you need to leave something stubbed out. If you have thoughts on what they code will need to be, leave a note about it. This is easily removed later.

4) Quirks. If the code does something that is not obvious, note that. Non-obvious side-effects, bugs, etc. Don't discover something painful, then leave the next person (possibly a future you) to re-learn that same painful lesson.

Code does stuff. Comments describe the code. Comments should not re-describe what the code does, they should be about the code and the code's context itself.

  • kondro 13 years ago

    3 & 4 are really the only two valid reasons to use comments, in my opinion.

    1 & 2 are both better solved with method abstraction. Comments describing what code is doing is always a code-smell to me. If you have 20 lines of code that is non-obvious, think about extracting it to one or more well-named methods.

    • katbyte 13 years ago

      his 1st point was not about commenting what code does but why it is done the way it is. I don't see how you can extract all the required information (including web links or rational) explain the rational behind a implementation into a function name.

          // unroll loop for 50% speed increase. Optimal offset 4
          // 3: 25%
          // 4: 50%
          // 5: 40%  
          for(i=0;i<x;i+=4) {
          ...
          }
      
      How could you extract that into a function name?

      2 is definitely more an opinion, but I use XML comments on every function, object, parameter, return value with a quick summery because it integrates into my IDE and is used to generate API and library documentation that is invaluable to developers who don't necessary have the code, only the documentation.

      • kamjam 13 years ago

        I use XML comments on every function

        I'm not talking about your opinion on point 2 here specifically, but your comment reminded me of a discussion I had with someone about comments... well, they were arguing (like the OP) that you should not use comments in your code but they would gladly use XML comments for the same reasons you have stated. So they would go to the lengths of helping out external developers with comments but not their own internal developers. Seemed very strange to me!

      • kondro 13 years ago

        I agree, performance optimisations like this definitely require significant documentation.

        However, for what most of us do, these optimisations should be rare. More emphasis should be placed on code maintainability than performance of individual components in most situations. Hardware is cheap, developer time is expensive.

theevocater 13 years ago

Comments are for why, code is for how.

Why is the counter < 5 or the balance >=0? Comments explain why your assertions are reality. Not every assertion is going to be as obvious as "balances have to be positive". If I had a dollar for every opaque assertion I blew up or ran into in code that had no explanation as to why something had to not be 0 or >1mil or null or whatever I would be a rich man.

eliben 13 years ago

I don't mean to sound patronizing, but if you're implementing counters or banging out numbingly-boilerplate business logic for websites, comments are indeed useless.

But when you're reading an obtuse 50-line function that implements some weird algorithm acting on some weird data structure, full of magic-like assumptions, you'd wish no one had deleted comments from it, or... had written them in the first place.

  • TimothyFitz 13 years ago

    Actually, that's EXACTLY the case I had in mind. Obviously I couldn't put a 50 line function with weird data structures in my blog post, or it would be unreadable. But the point is that comments for that function are bad! They'll rot if you ever change the function or the assumptions at all. Instead, you should break the 50-line function up into smaller functions, and add assertions and test cases for all of those "magic-lik assumptions." Then get in the habit of reading tests first. Now your code-as-comments will never rot.

    • drobilla 13 years ago

      No offence, but this is incredibly naïve, and it's kind of obviously an opinion that simply stems from working on things that just aren't that conceptually complicated. Some things are actually conceptually complicated, and the why is not at all obvious from the what, no matter how finely you slice the what. Code, inherently, describes what. A sparse set of higher level proper sentence comments describing the purpose of the overall goal for the next part is practically required to make code like this actually comprehensible. For some things, something approaching Literate Programming is best, which is nearly the polar opposite of "comments are bad".

      Implementing an advanced data structure is a good example of this. Things that took theoreticians some time to discover, and write/publish in a paper, are not things a random programmer is just going to inherently know from a completely uncommented implementation.

      Extrapolating "all comments are bad" from a few examples of pointless comments on mind-numbingly simple and obvious code (which are indeed bad) is silly.

    • barrkel 13 years ago

      OK. But the algorithm is over a 1000 lines split up into perhaps 50 20-line functions, and it's mysterious how the whole works by looking at the parts.

      I have one particular piece of code, that I wrote, in mind. It was to implement anonymous methods in the Delphi compiler. Given an AST for a method from the parser, it had to rewrite the tree to turn captured local variable references into field accesses on a heap-allocated stack frame, turn anonymous methods into methods on this heap-allocated stack frame, and all while minimizing the number of passes over the tree. And this has to work recursively, which adds a surprising number of wrinkles about the ordering in which you can do things.

      So for example any given pass may be building up accounting data needed by later passes. This is somewhat mysterious, because it seems like busywork; and why is it doing this here? Why not fold one pass into another? Why not move work between passes? Well, the subtle ordering problems are not clear at all when you're looking at things at the function level. You can only understand the pieces when you already understand the whole.

      And this is why there is a very long comment block describing how this stuff works. Because figuring it out by reading the code is too expensive.

      (That ~1000 lines of code took perhaps 4 months to write; having to integrate with rest of a large complex codebase adds countless more wrinkles.)

    • katbyte 13 years ago

      I've worked on code like that, and i'm sorry but i would rather read a 50 (or even couple 100 if appropriate) line function implementing specific functionality that is well written and documented with comments then have that critical information split up into a multiple functions and test cases spread out over multiple files. Sometimes functionality belongs together and it would be far more difficult to get that all that disjointed information into coherent mental model.

      Not to mention how test cases and function names would just not cut it for explaining things like why the current implantation was chosen over more obvious, simpler ones, why the magic like assumptions are necessary and documenting the bugs/quirks in the underlying library or framework that are not obvious. Things like why call object.SetValue() instead of property object.value = x? Or Free memory from this call here, but not here, because the framework takes care of it.

      I prefer commented code, even if it is over commented, because at the very least it is a way for the last programmer to explain why she implemented things the way she did.

    • kamjam 13 years ago

      But the point is that comments for that function are bad! They'll rot if you ever change the function or the assumptions at all

      Do you leave unused functions in your code when you refactor? No. So refactor your comments, or delete them if they are no longer applicable, when you refactor your code.

      I have been saved many times by comments in my own code, because you know I work on a lot of stuff, sometimes coming back to it after years and I hope I have developed as a coder and so my mindset is now different and a lot of the time I do wonder WTF was I doing here!

      This is the opposite of your post http://tech.collectedit.com/post/2012/11/12/Comment-your-dam... which I tend to agree with a lot more.

      Your code tells me what you did. Your comments tell me what you intended. Help me out. Help your future self out!

saidajigumi 13 years ago

I'll agree that good comments don't reiterate what is plain from the code. Truly clear, self-explanatory code is a joy to read. But the process of coding usually boils away any notion of why, leaving only the brain-compiled machine that implements the how. It's the original use-case, high-level policies, implicit contracts and so on that comments should generally focus on. Especially, as the author notes, since TDD infrastructure and culture has gotten so much better at covering the "how" in recent years.

Also, sometimes the code is sufficiently brain-compiled that it's utterly inscrutable. Early in my career I wrote a fast interrupt driver for the company's main product that had become quite heavily optimized, and practically every line depended on nuances of the related hardware's functionality. This code was written in two-column code/comment form, and had more lines of comments than lines of code. This was necessary for it to be at all maintainable. In theory, a later refactoring might have simplified this state of affairs... but that opportunity never happened.

acc00 13 years ago

the comments in the gc example are not there because the language this is implemented in is less readable than python; they are there because the problem the code solves is non-trivial and requires documenting. however clean, readable and trivial your code is, you can't express your thought process with it. and when you're doing sophisticated things, that is very important to convey.

fotbr 13 years ago

Take it up with programming 101 instructors around the world, who beat it into their students' heads that "every line" / "every function" / "every class" etc needs comments, no matter how redundant or bad the comment was, because "good code is commented". No joke, fairly well respected science & engineering university, every line of every program through the first three semesters of a CS program was required to be commented. After a while, slapping in useless and bad comments became habit, required for the assignment to even be considered for grading. It takes a while to break that habit.

  • kevinpet 13 years ago

    Really? Find me one today. Find me a textbook that says that published in the last ten years. I'm tired of seeing this trotted out as a straw man of the crowd who thinks sometimes comments are good.

    • fotbr 13 years ago

      I just know what I and my classmates went through. The commenting requirement wasn't from any book, it was a requirement coming from the professors who taught the courses.

alexchamberlain 13 years ago

I've recently read Clean Code by Robert Martin and now totally agree with the OP; everyone should go and read it, though it's full of annoying Java, it does apply equally to proper languages.

  • Xion 13 years ago

    The reason you call Java annoying is exactly the one why Java code is so conducive to refactoring practices described in Clean Code: it mandates great verbosity.

    Everything in Java is Big Deal, even something like a simple loop going through a collection and applying a one-liner to every element. In Java, you have to divide things aggressively for code to remain readable and maintainable. Otherwise it's way to easy to lose the big picture.

    When methods are few lines tops, their names are descriptive, and you have explicit types of arguments and return values, it's no wonder you hardly ever need to comment anything.

    Other languages can be very different in this regard. Take Python, ironically the language author's using in his examples.

    Python is terse and expressive; does not specify types in code; has everything as first-order values; prefers short names due_to_naming_convention; and makes extracting code into functions a significantly bigger deal (everything is public, needs to have docstring, etc.). Those traits often need to be offset by a little more prose than you would put into code in other languages.

    So while Clean Code certainly sounds convincing (I know I treated it almost like a revelation), it needs a little more perspective. Commenting practices are just one more tool that you need to match to the job - and language - at hand.

    • alexchamberlain 13 years ago

      Erm no... I'm a C++ developer. I call Java annoying because it is inefficient and has a garbage collector.

      • Xion 13 years ago

        And how these particular flaws of Java are relevant to the comments-or-not discussion at hand?

hvs 13 years ago

A conversation I once had with a junior developer:

  Him: I don't write comments. My code is self-documenting.
  Me: Apparently, you have never attempted to read those documents.
Comments should include the why's of code's existence (e.g. business rules) as well as any bigger picture information about the code for usage (e.g. "This function is for X, if you are looking for the function for Y, you are probably looking for Z").
moocow01 13 years ago

This doesn't address the practical real-world problem...

Most developers are under at least moderate pressure to deliver and usually their priority is this...

1) Make thing appear to work

2) Make thing actually work

3) Clean up code to pass a code review or not be yelled at by a coworker

4) Comment where things are necessary

In many cases we barely get past step 1 and a half and usually its not even our fault - the business case has been mostly satisfied and according to the mucky mucks its best to move onto the next feature. Yes most of us dream of places where we can craft our code to oblivion but its probably not the average reality unfortunately.

I think its great when somebody takes the time to comment - commenting is not fun and has very little upfront reward but can be a lifesaver when traversing complex logic. If you have the ability to leave a profuse amount of comments I can hide them when I dont need them and use them when I have no idea whats going on - comment as much as you like.

katbyte 13 years ago

Without comments how do you produce documentation for your code?

I put XML comments on every function, object, property etc giving them at the very least a short summary. These are then compiled into documentation xml that integrates with the IDE providing pop-up documentation for objects and functions without needing to see the source code. This xml is then compiled into actual html documentation is also used for APIs and libraries that other developers use without any access to the code.

Maybe documentation falls outside of the purview of source code comments... but i don't think so and i find it really handy to have the source code self documented with comments keeping docs and code in the same place.

eps 13 years ago

Ah, to be young and wild, and have most of my limbs again...

Try expressing a relatively complex state machine with asserts. Then come back in a month and try converting all those asserts back into few English sentences.

kondro 13 years ago

Comments prove that naming is hard.

If we as developers spent more time on using better names for our objects/methods, we would need less comments.

jamesmcn 13 years ago

and also vi > emacs

But seriously. Comments are useful. Don't over use them, don't under use them. If you are being dogmatic about your comments, you are probably doing it wrong. Autodoc comments can be nice, when done properly.

slajax 13 years ago

Comments can be super fun. Especially if you are into fabels and can liken the purpose of your code to the journey of a hobbit or similar creature from the shire.

halayli 13 years ago

It's more accurate to say: I hate bad comments.

Peaker 13 years ago

You can start to use your commit log as the comments.

kaonashi 13 years ago

tl;dr

Comments suck, documentation rocks.

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection