1. 47
  1.  

  2. 10

    Comments can lead you astray, because they get out of date. The code is the only source of truth.

    The reason I’ve never liked this sentiment (and the OP is only quoting it) is that I consider comments part of the code.

    1. 5

      You can also forget to update a piece of code when you’re making a large swooping change, but that will most likely just crash or produce incorrect results, which makes you aware that you “missed a spot”. Comments don’t have this property, so they will more easily be missed as part of an update.

      1. 6

        Large swooping changes are exactly the scenario where extra time spent on documentation is warranted. Plus, if the comments are co-located with the code, it’s easy to catch missing/incorrect docs in a code review (which again, should be performed for any large swooping changes!)

        1. 4

          On the other hand, words-in-sentences-in-comments are better than words-in-variable-names at describing requirements, and assumptions, and what direction the code should evolve in. Incidentally all things that are more likely to start correct and/or remain correct across updates, while code is more likely to contain or introduce defects.

          Secondly, if I’m gong to figure out the intent and assumptions of a piece of code, I’m basically reconstructing what a comment would say, and I’d rather have the comment to start with.

          Thirdly, even if the code is updated and the comment is not, having the ‘previous’ comment there is a scaffolding that’ll help me figure out the new code quicker. Diff to the previous intent is likely to be small, after all. Of course I’m going to need to figure out whether the new code is correct or the old comment; but that’s better than figuring out whether the new code is correct without a comment.

        2. 2

          My tests can’t check my comments, though.

          Granted, they can’t check that my function/method/procedure names match what they do either.

          1. 1

            Rust can! Sort of. They’re called doctests and they make sure your code samples compile and assert correctly, just like regular tests!

            I like them because examples doubling as simple tests also encourages you to write more examples.

            1. 1

              I almost feel like that misses the point of this article though? If I’m writing an explanation of the happy path of a function, there’s likely not really anything I can put in a comment that doctest would be useful for. It’s most likely just prose.

              Where doctest does work very well is if I’m writing comments that get turned into API documentation, but that’s an entirely different set of comments than what Hillel is describing in the article.

              1. 1

                That’s true, hence “sort of” in my comment. But doctests are better than nothing, even if they can’t check prose comments. You don’t need to refactor a crate into a separate library to document some strange behavior of a particular function with examples.

                The author does mention two cases where examples could help:

                • Tips: “This function is currently idempotent, but that’s an implementation detail we intentionally don’t rely on.”
                • Warnings: “This routine is really delicate and fails in subtle ways, make sure you talk with XYZ if you want to change it.”

                But otherwise I agree. The “tests” for comments are rigorous code review, which unfortunately falls under the “try harder” class of solutions.

                Also, even if it’s only tangentially related, I think doctests are pretty cool and worth mentioning.

              2. 1

                I’m aware of doctests, but those are code again, even if they are written “in comments” – the comment less, code better crowd absolutely treat all tests (doctest or no) as part of the solution.

          2. 5

            Far from being a reliable metric, but comment density should be inversely proportional to the total team’s expertise on a given language.

            A Fortran project that is absolutely clueless about C could benefit from an “increment i by 1” comment, pretty much in the same way a team with no bash experts could benefit from the “copy array” comment. A team of C experts would not benefit from the former case, and a team of bash experts would not benefit from the latter.

            In cases where the cardinality of the team is one, the idea of adding comments becomes a simple matter of confidence. If you think you don’t have enough expertise in that language, feel free to add comments to the source code as you like.

            1. 1

              But… the expertise of the team is not fixed?

              1. 1

                Neither is code. New entries will have less and less comments and, over time, files that are constantly maintained should experience a drop in code density as well.

                (Or so it goes in my head.)

                1. 1

                  If code drops comments over time and we don’t get an associated rise in readability (that is, presuming comments would still have been useful) doesn’t that make the recipe for unmaintainable legacy codebade? The team’s experience level is not likely trending up with time, churn will bring the domain experience down but change the language experience randomly as hires of wildly differing experience levels onboard.

                  1. 1

                    Oh, I believe I might have misinterpreted your original question. As a matter of fact I assume the expertise of the team is (ideally) not fixed.

                    I can see the scenario you’ve described happening to projects that use languages with low overall adoption and poor developer retention, but I would not expect a reduction on comments density in this scenario—at least not one that is correlated with the mentioned factors.

            2. 4

              I find that when I write code, I typically comment the “what” as a last resort.

              When writing BASH, there’s far too many archaic invocations that are difficult to pop into a search engine. I almost always document the “what” in those situations, because I want to save the next engineer time when they pop in to make a modification or fix a bug.

              I generally see documenting the “what” as necessary but not ideal. Kind of like technical debt. If I need to explain what is happening, I probably didn’t structure the code well enough to communicate what is being done.

              That all said, I feel like documenting the why not the what is like any practice. It’s a good “rule” to consider, and break when it makes sense.

              1. 2

                I generally agree with this. I spend a lot of time commenting my code - I probably wind up with too many comments, in fact. But in general, I think it’s better to err on the side of verbosity, because people can ignore unneeded comments but they can’t summon up from the aether perspective on what the code is supposed to be doing. Likewise, “What” and “Why” are in my eyes relevant but not decisive when deciding what comments to put in; the real criterion is whether the code is clear to someone who didn’t have the expertise to write it, and I like that this article calls out specific examples of when “What” comments meet that bar.

                This reminds me of the old saying I’ve heard about Perl - you can know all the Perl you like but it won’t prepare you to read somebody else’s Perl. That’s the kind of situation where “What” comments are valuable, when the reader might be easily able to grok the semantics of the code if only they could parse the syntax.

                1. 4

                  I think it’s better to err on the side of verbosity, because people can ignore unneeded comments but they can’t summon up from the aether perspective on what the code is supposed to be doing.

                  The problem with that is that you need to actually read the comment to know if you can ignore it, and if there are a lot of comments that can be ignored people will stop reading them too.

                  I think that talking about “comments” in general is perhaps too, well, general. Not all comments are the same: a comment describing a function is quite different than an inline comment describing a line of code. And a simple comment like b=( "${a[@]}" ) # copy array is also not quite the same as a bunch of large blocks of text smack in the middle of the function.

                  Being too verbose in things like function descriptions isn’t too bad. But inlining a lot of huge verbose comment blocks … meh, I’m not a huge fan.

                  I found that in general, the best trade-off is usually to write a detailed description in the function/class/package/whatnot comment, and then be a bit more sparse with comments in the actual code.

                  1. 3

                    I document and comment… a lot.

                    Recently at work, for example, I’ve been helping to clean up and standardize tox configs. And the files I’ve been producing are probably mostly comments by line count. But I think it’s justified – not everyone I work with has used tox before, and having a well-commented config that explains what each section is doing and why makes it a lot easier (I hope).

                    I also tend to pretty much obsessively comment bash scripts, because otherwise there’s zero chance I’ll remember why they’re written this way and not that way (recent example: a script where I had to do $* and explicitly not $@, and commented to explain both what $* is there for and why not $@`).

                    In code, I tend to comment a fair bit, but because most of it is Python I put docstrings on everything and both personal and work projects use Sphinx to document, copiously.

                    1. 1

                      One thing that might be nice is if we could have different “kind” of comments.

                      In my editor comments stick out quite strongly (just the default Vim colourscheme), which is a good thing IMHO. A lot of other colour schemes tend to put comments more in the background by greying them out in some low-contrast way, which seems to be the de-facto default these days.

                      It would be nice if you could mark the “importance” of comments: some “hey, here’s a longer explanation in case you’re not familiar with this”-type comment could be put in the background (or even be collapsed), while a “yo yo, read this, it’s important!”-type comment could stick out more.

                      That would probably make everyone happy if used correct.

                2. 2

                  Comments bloat files

                  Ugh yeah I agree, it’s really annoying. The more comments you have, the less code you can have on the screen at once, and also the comments are visually distracting. I think better tooling can deal with this, but “better tooling!” isn’t much better than “try harder!” as an answer.

                  Hm, how would this work? The only thing I can think of is stuff like collapsing comments, but I’m not sure how desirable that is; after all, you do actually want to read the comment?

                  edit: one solution might be something like this; although there are a number of practical UX issues with regards to editing the “uncommented” version that don’t really have obvious solutions. Although that will be easier to solve in a non-character/terminal based editor like VSCode where you can do more graphical stuff.

                  1. 1

                    One thing that I don’t think gets discussed enough when people talk about this is the target audience. It’s kind of a cardinal rule of tech writing (or writing in general, really) that you should know which audience you’re writing for, but often times, it seems like code comments are expected to target all possible audiences.

                    If your code is liberally sprinkled with comments that explain the syntax of the programming language, people who didn’t previously know the language very well are going to find it a huge time-saver and will thank you. But people who are already proficient in the language will see it as annoying clutter that makes it more time-consuming to skim the code. On the flipside, a concise comment about requirements that assumes a baseline level of domain knowledge will be very helpful for someone with that domain knowledge (they won’t have to try to fish your intended meaning out of a sea of redundant introductory text) but will be confusing gobbeldygook to someone who isn’t up to speed yet and is just trying to follow the code at a low level.

                    Given that many code bases will be worked on by people with a variety of backgrounds and skill levels, I’m not sure it’s possible, even in theory, to come up with a commenting policy that documents the code optimally for everyone.

                    1. 1

                      The author claims this is shortest:

                      b=( "${a[@]}" ) # copy array
                      

                      But this is 27 characters (including the comment).

                      The following is quite a bit shorter, and clearer:

                      copy_of_a=( "${a[@]}" )
                      

                      If you want it clearer still, define a function. Then you don’t need “# copy array” every time you want to copy an array. DRY.

                      1. 7

                        Then you don’t need “# copy array” every time you want to copy an array. DRY.

                        I highly recommend you read the post more carefully. It really seems like you have missed the point here.

                        1. 5

                          But this is kind of a low-hanging fruit, isn’t it? Now assume that a and b bear some semantic context, say, about the problem domain. So you are basically replacing b by a potentially confusing variable name just for the sake of removing the comments.

                          I agree that this might be a better option in some cases—maybe most of them—but it is not a silver bullet.