1. 15

  2. 9

    When I have to implement something tricky I often write out everything that needs to happen, in plain English, as “useless” comments and then write the code that implements that line of English below it. Once every line of English has some code below it, I should be done. I run it, or run the tests, or whatever, and once I’m convinced that it works, I delete the comments (or turn them into “useful” comments, if that seems warranted).

    1. 1

      I do this sometimes also, although not as often as I used to. I’ve always wanted to be able to leave them in though, and also a first-class way to have comments linked to a “block” of code (a group of statements/expressions, not a semantic block).

    2. 7

      I always try to leave comments with the why not the how. When something is not obvious from the code, like how the usage of an api in seamingly non-obvious way yields the wanted result or why a constant has a certain value etc. etc. I do this more as a reminder to myself, since I tend to forget these details after a few days.

      1. 4

        I used to work at a company where our team lead was insistent that every line of code be accompanied by a comment.

        The whole codebase looked something like this:

        // Increment x by 1
        x = x + 1;
        // Print x to the console
        // If x is 2
        if (x === 2) {
          // Print that x is 2
          console.log('x = 2');
        } else { // Else if x is not 2
          // Print that x is not 2
          console.log('x is not 2');
        } // End if x is 2

        If that wasn’t egregious enough, in the situations where a comment would actually be useful in understanding the code the comment attached to a particular line would contradict what the code was doing.

        All that to say, I’m unconvinced by the author’s argument that useless comments like this are useful to anyone.

        1. 9

          I also want to comment on this claim in particular:

          Comments which are at the same level of detail as the code may not be useful to you as a fluent reader and writer of code, but they are to someone like me who is still figuring out how to read and write code.

          I think that this is the wrong way of approaching teaching someone how to read code. If your primary purpose is education then, by all means, litter the code with explanatory comments, but it doesn’t make any sense to keep commenting every line of production code like this just so it’s accessible to someone who isn’t familiar with reading code.

          Teach them to read the code so that they don’t need redundant comments.

          1. 4

            I agree that these comments aren’t useful but there’s an important asymmetry to consider:

            • A novice programmer can easily remove comments that are pointless.
            • Only a more experienced programmer can add missing comments that are necessary.

            This means that I’d always encourage people to over-comment rather than under-commenting. That said, your example is actually doing both. Why is x being incremented by 1? What is the importance of 1 here? Why do we care if x is 2?

            1. 4

              But that’s actually the thing. Instead of writing these useless comments (“look, there’s a comment, so this is well commented code” the effort could be spent instead on useful comments explaining why. Sometimes even every line explaining why makes sense. Although in many cases refactoring the code helps a lot because e.g. good names of variables and functions can be a big boon to understandability and unlike comments they don’t bit-rot.

              1. 2

                Exactly this. If each line of code had a comment that actually provided some valuable insight that isn’t obvious from the code itself, I wouldn’t have such a problem with this style.

                In my experience, the hard and fast rule that was put in place of having a comment for every line led me to just start ignoring every comment in sight. Useful comments no longer stand out as signposts because they’re buried under the weight of all the noisy ones.

                I still maintain that code can (and should) be refactored for clarity prior to introducing a comment. For instance, in my contrived example above the conditional could be rewritten like so:

                const enableSecretFeature = x === 2;
                if (enableSecretFeature) {
                  // ...
                } else {
                  // ...

                This provides the why behind what the code is doing, and it does so without needing a comment.

          2. 4

            Personally, I’ve never liked the advice that writing obvious comments is bad practice—probably because I write obvious comments all the time.

            This is fun and games while it is correct but when you run across a comment that is claiming the opposite of what the code does, what now?

            // Add a horizontal scroll bar
            newScrollBar = new JScrollBar(scrollBar, VERTICAL);

            What’s the correct behaviour? Should you fix the comment? Should you fix the code? Should you leave it alone if you’re not directly affected by it? With just the code the problem isn’t really there since there is one source of truth. It might not be correct but at least there’s no contradictions because the code does what the code says it does.

            The problem with comments is, that they’re non-executable, so the person changing the code changes the code otherwise the change will not happen. But will they remember to change the comment? Maybe, maybe not. This isn’t even a hypothetical case, I’ve seen cases where the comment claimed the exact opposite behaviour than what the code did.

            1. 5

              What’s the correct behaviour? Should you fix the comment? Should you fix the code? Should you leave it alone if you’re not directly affected by it? With just the code the problem isn’t really there since there is one source of truth. It might not be correct but at least there’s no contradictions because the code does what the code says it does.

              I’ve found those cases incredibly useful, because they tell me the code diverged. Something changed; why? Does other code assume the scroll bar is horizontal? Was that code switched when this snippet was switched to vertical? Does this code/comment divergence help me track down the bug I’m searching for?

              Without the comment I wouldn’t know that something interesting happened and wouldn’t even think to git blame it, but now I know that there’s historical information here.

              1. 3

                I’ve found those cases incredibly useful, because they tell me the code diverged. Something changed; why?

                Usually, because I slipped as I was typing the comment. I use the wrong word all the time when speaking and writing, and need either some testing or a careful reader to notice.

                There’s nothing insightful to be gained from my thinkos and brain farts: they’re also in my multi-paragraph expository comments, but at least there you usually have enough context to realize “oh, Ori is a sloppy writer, and clearly meant this”.

                1. 2

                  The thing is: for the most part, 99% of the cases, this is because the code was changed but the comment wasn’t (very much according to Occam’s Razor) so what you get out of this is wasting your time with needless investigation of something that’s not actually a problem and then fixing the comment or just removing it outright.

                  1. 2

                    If you are certain the code is right and know the comment is wrong, then take 30 seconds to fix the comment to match the code and move on with your life. Not a big deal.

                    If you are uncertain whether the code is wrong or the comment is wrong, then that indicates a hole in your understanding. That hole would exist whether or not the comment was there. So thats a useful indicator that you should investigate further.

                    1. 1

                      The comment makes understanding that line actively more difficult. If you’re reading the code for the purpose of coming to some initial understanding of a codebase then you’re going in with holes in your understanding and this inconsistent comment creates yet another hole.

                      You’re suggesting that if I go to a random Github repo I’m not familiar with, start trying to read the code, and find a comment that is blatantly and objectively inconsistent with the code it’s attached to, that’s not actually a problem because if I just understood the codebase I’d know which to trust.

                      You’re onto something there. That’s exactly the point: if context makes it clear which to trust, then you don’t need both, you just need the (correct) code. If we can make the assumption the misleading comment won’t matter because anyone reading it will know that the comment is wrong, then what is the comment doing there at all?

              2. 4

                Saying code comments are useless is a judgement from us as fluent readers of the code. It disregards the value comments have for someone less fluent than yourself who is either reading or writing code.

                If you’re trying to teach people a language that they don’t understand, you’re going to need to do a LOT more explaining:

                // Add a horizontal scroll bar
                hScrollBar = new JScrollBar(scrollBar, HORIZONTAL);
                add(hScrollBar, BorderLayout.SOUTH);

                May need to become:

                // Add a new horizontal scroll bar.
                // Horizontal scroll bars are what we call the GUI element that
                // allow you to move a widget's visible frame side to side instead
                // of vertically (see https://tutorial.com/diagram.jpg).
                // 'new' is a keyword that indicates that the following word is a class
                // name, and that  the constructor `JScrollBar.JScrolBar()` is to be invoked.
                // This is used to initialize the scrollbar object, and set it up as horizontal.
                hScrollBar = new JScrollBar(scrollBar, HORIZONTAL);
                // The add() function is implicitly called on the `this` object, and takes both
                // the hScrollBar we created in the line above, the current container object,
                // and uses the BorderLayout.SOUTH constant to indicate that it goes on
                // the bottom of the container.
                add(hScrollBar, BorderLayout.SOUTH);

                The problem with these ‘useless comments’ is that they’re generally not sufficient to teach someone that is unfamiliar with reading code, and unhelpful for someone that is.

                1. 1

                  Could you comment also mention what scrollBar is, why it is necessary and how it differs from hScrollBar? I have no experience with Java and would like the explanation of everything directly in the code.