1. 25
  1.  

  2. 14

    I dislike overly flowery language in comments and go out of my way to make it short and concise when feasible. So this:

    # EVEN BETTER:
    # Try to read the configuration file, but it's OK if
    # it's missing because we don't require a config file.
    

    Would be much better phrased as:

    # Try to read the optional config file.
    

    Which conveys exactly the same information in much fewer words, saving mental overload in reading it, and a line of text as well.

    1. 10

      It’s presumably clear from the code that it’s trying to read the config file. What’s missing is why it’s optional.

      1. 3

        I don’t think “explaining the why” is the only purpose for comments; for example this comment would be perfectly fine as a function comment:

        # Try to read the optional config file.
        read_confiig() {
            ..
        }
        

        Or, maybe if you have a more linear script to break up chunks:

        # Do task foo
        .. bunch of lines ..
        
        # Try to read the optional config file.
        .. bunch of lines ..
        
        # Do other task
        .. bunch of lines ..
        
        1. 1

          That’s what function names are for.

          1. 3

            I had a somewhat similar discussion about this on HN a few weeks ago (I go by “Carpetsmoker” there):

            I find that names are rarely all that useful anyway, since you can’t capture the full effect of a function in a name in most cases. I once named a method mkdir() and then someone commented that it was “obscure”, so it got renamed createDirectory(), then someone commented that it was actually creating all intermediate directories, so it became createDirectoryTree(). This still doesn’t really communicate that it won’t error if the directory already exists, so I commented it should really be createDirectoryTreeOrDoNothing().

            There are many more examples: str_to_int() probably doesn’t capture what it does on common errors and edge cases (exception (which?), return -1, etc.), but you do really want to capture that in the function name? I think a function comment is much more appropriate for that.

            Additionally, (very) long names everywhere make code harder to read IMHO. There is some friction between usability and descriptiveness here.

            In short, it’s a function name, and not a function description. And while the name can (and should!) certainly be descriptive to some degree, I don’t think we should confuse the two concepts.

            1. 3

              ensurePathExists?

              1. 2

                ensurePathExists makes me think it’s asserting the path exists and raising an error if it doesn’t. require and ensure are the standard names for pre/postconditions in design-by-contract.

                1. 2

                  That the wrong use of the word then. Perhaps you’re thinking of “verify”. Ensure imples action if necessary.

                  1. 3

                    Ah, that’s a sign to me that “descriptive names” can still be deeply ambiguous. I am not using “ensure” in the wrong way; “ensure” as “assert postcondition” has been the standard term in formal verification since at least the 1980’s. Maybe you’re the one using the word wrong!

                    Or maybe both of our backgrounds are valid and we’re both being reasonable in how we interpret the name. Maybe we can’t unambiguously encode our intention in the name of a function.

                    1. 2

                      Naming, as we well know, is one of the hardest things in computer science.

                      But comments can’t fix that problem because it’s equally possible to have a comment that is ambiguous or misleading.

                      1. 3

                        Comments can go a lot further, because they don’t have to be valid method names. We can use multiple lines, spaces, etc.

                        Compare

                        # If we don't have a path, something deleted it since we created it
                        # So we'll halt and figure out what's wrong with the environment
                        def ensurePathExists()
                        

                        With

                        # Creates all the folders if they don't exist
                        # Otherwise does nothing. Idempotent.
                        def ensurePathExists()
                        

                        Same name, different intentions, different meanings, all captured in the comment.

                      2. 1

                        It seems that “ensure” means “the program will not continue executing if this is not true” in both cases.

                        1. 1

                          According to the description @arp242 gave, the program will only create the directories if they don’t exist! While for postconditions, we’d be halting if the directories don’t exist.

                          1. 1

                            Well, what I mean is, regardless of how it’s done - whether the function creates the directory or panics - the rest of the program can be sure the directory exists. Either because the directory was created, or because the program wouldn’t continue running otherwise. I think both of your interpretations of “ensure” are correct and even consistent with each other.

                2. 2

                  That is a good point. Documentation and comments can describe these much better than a single symbol.

                  On the other extreme, crtdry could mean createDirectory or certificate dirty.

                  All about balance I guess…

                  1. 1

                    long names everywhere make code harder to read IMHO.

                    100%

                    In short, it’s a function name, and not a function description.

                    A fair point, but one easily abused.

                    That is, if you cannot find an accurate name it usually indicates one of the following:

                    1. You haven’t thought hard enough. That is, a good one exists but you haven’t found it yet (eg, @adsouza’s idea of ensurePathExists might be a good solution to your directory example)
                    2. (more likely) Your function is doing too many things, and your inability to find a good name is alerting you to deeper design problems.
                    1. 3

                      No matter what name is chosen, nothing will be as crystal-clear as a brief well-written comment describing what the function does, with possible edge cases, and how it will behave on unexpected cases. Are you sure everyone will be on-board with your meaning of “ensure” here? I wouldn’t take that bet.

                      Your function is doing too many things, and your inability to find a good name is alerting you to deeper design problems.

                      It … happens. We can’t all keep refactoring, and I don’t think that “I can’t find a good name for this so lets refactor” is always a good option (although of course sometimes it is).

                      Some things are fundamentally quite complex with no easy way to break it down in smaller pieces. Depending on your environment, it may not be obvious if str_to_int() will use in-band error reporting (e.g. return 0 or -1) on the input asdf or throw an exception. It may also not be obvious if it supports negative values. Capturing all that in the function name strikes me as unreasonable.

                      Perhaps most importantly, some functions that do a lot aren’t necessarily “code smell” (especially not if they call other, smaller, functions). API design is mostly just plain ol’ user interface design, and splitting the API for business logic like invoice.create(creditor, debtor, amount) in to smaller parts is not necessarily a good idea.

                      Either way, in general I would err on the side of caution and add a single-line (80 column) function description to most functions (especially public ones), which should remove any ambiguity about what a function does and inform future readers – possibly from a different background than you – concisely and accurately what a function does.

          2. 5

            Not from the article, but from one of the comments:

            I’d go one step further and insist on proper spelling as well. If I can’t trust you to spell English correctly, how can I be sure you’re spelling function names correctly?

            If I started doing this with my own employees — who are all Russian — I hope for the sake of their own dignity, they’d all tell me to go and do something unspeakable to myself, and then quit.

            My colleagues are invaluable. They’re helping me build my business, and they do excellent work. I wouldn’t dare start drawing red lines around correct usage of English. I wouldn’t even do it with colleagues who speak English as a first language. If an American colleague were to write “the performance here could be better, but it doesn’t matter for us and I could care less”, even though I find it annoying that Americans constantly get this standard phrase backwards, I wouldn’t dare get precious over it in a software project.

            Merge it and move on. If it bothers you that much, send a correction in a commit or PR after the fact.

            1. 4

              This seems to be purely a personal preference, entirely orthogonal to comment quality.

              // add 1 to i
              i += 1;
              
              // Dear reader, as you may see, the following line will 
              // add the number one to the variable called "i".
              i += 1;
              

              They’re both equally awful.

              The IMHO useful rules are:

              • Comments should state why, not how
              • Comments in the form “and now do that thing” mean you want a function, not a comment
              1. 3
                // sometimes the below would
                // segfault. This seems to fix it:
                len--;
                

                I think explaining why is useful in the way a smoke alarm is useful, but I’d much rather not have a fire in the first place.

                1. 2

                  At least it explains why that line of code exists, and is a start to tracking down the root cause.

                  1. 1

                    Better to not put the bug in the first place, though, agreed?

                    1. 6

                      That is usually easier said than done.

                      1. 3

                        It now occurred to me, that writing such a comment is in a way an act of bravery and humility: of accepting one’s own imperfection; that we know we may not always be able to do something perfectly. And then, not hiding it under the carpet, but explicitly communicating our vulnerability to the reader: “here’s where I reached some boundary I could not cross; not able to, or having to trade my attention off for something else, in the limited span of life we have available; I respect and embrace the thought, that you, my dear reader, may be able to improve this; more than that — I want to help you, by giving you any important hints I think may let you make the best use of your time and intelligence.”

                        1. 1

                          This week I removed a warning log line from code so I’d get meaningful prints only. The comment above it explains the line right before the log line is critical due to a bug in the code.

                          The comment below that one reads “2015-03-20: is this still the case? When can we delete this code?”

                          I then carry on with my job, knowing that people far more familiar with the codebase than I have tried and failed to remove that bug.

                  2. 3

                    Comments are for explaining why something is the way it is, not what some piece of code is doing. Rule of thumb is assume the reader knows how to read code.

                    So, in your example where you explain what the code is doing (namely, incrementing by 1), that comment is bad because it’s explaining what’s going on and not why you’re incrementing by 1 (if such an operation requires an explanation in the first place), not because the comment isn’t a complete sentence. When explaining why something is happening in code, complete sentences are not only good for comprehension, it’s the professional thing to do

                    1. 2

                      “Increment i by 1”-style is really, really important when you have constraints that limit how “clean” your code can be. A couple of major cases are performance stuff and formal verification (functional decomposition “cuts” your information space in a way that’s murderous for specification). Also with very dense notations: a J expert knows exactly what count =: ({. ,. #)/.~ does but a beginner might not, so I could comment with an explanation.

                      1. 1

                        That is true in example code used in a language tutorial. But for production code, it seems like overkill. It should be possible to at least assume the reader knows the language in question!

                        1. 2

                          The thing is, every mainstream language is large enough that you have a situation roughly like the following, where the letters may correspond to language features, standard lib packages, conventions around naming and package organization, or higher level idioms:

                          • A, B: Everyone knows them, even newbies
                          • C, D: Most junior devs would know them
                          • E, F: Professionals in the languages usually know them, but probably not junior devs
                          • G, H: Even many professionals are not familiar with them

                          Thus “knows the language in question” is not a binary flag, but a many-dimensional object with spectrums of “know” along each dimension.

                          The appropriate amount to comment, then, depends on what level of expertise you assume, the number and type of devs you foresee working in the codebase, the amount of dev churn on your team, and so on. Erring on the safe side of explaining too much is often the right move. But overdoing it can be a problem too. Judgement dictates.

                          Personally I see the problem of too little explanation more often than too much, but I’ve seen both.

                      2. 2

                        entirely orthogonal to comment quality.

                        I basically agree with your post, but I’d amend the above to “theoretically orthogonal but in practice correlated.”

                        That is, I think the author has a point with his broken windows observation. All else being equal, a team following this rule would be more likely, I’d guess, to have good comments than one that didn’t. It’s just one of those things that makes you stop for a few seconds and put more thought into what you’re typing. It won’t always work, and in the hands of blind rule followers it might encourage needless verbosity, but still, I’d guess for most teams this is a net positive rule.

                      3. 2

                        Comments that are redundant when paired with the code annoy me a lot and seem really common in the wild.

                        PSA, Write comments explaining things the code doesn’t show.

                        1. -1

                          Comments should almost never exist. They are untyped and often get outdated and then cause more harm than good. There are no refactoring tools for them. It’s generally a sign that the language is lacking necessary features or the code needs to be rewritten. An exception can be made for temporary comments like “todos”, but that’s it.

                          Instead of comments, make your code describe exactly what it does. useLongVariableAndMethodNames. Never have single letter variables(Yes: even use the word “index” instead of “i”). Put the time you would spend writing comments into better tests and code.

                          Check out the book Clean Code if you want some great advice.

                          1. 12

                            I don’t see how using “index” instead of “i” helps. If you’re obviously looping through an array, and the for loop isn’t stupidly complicated, the letter “i” conveys exactly as much information as the word “index” to the reader.

                            Nobody read “for (i = 0; i < len(elements); ++i) do_thing(elements[i])” and wonders what that cryptic “i” could possibly mean.

                            1. -4

                              Next generation dev tools will rely increasingly on machine learning to aid in development. When you write “index” instead of “i”, you are providing a whole lot of additional information (reduction in entropy through narrowing of the search space). This helps folks building data driven tools.

                              You can start using this sort of thing today. I highly recommend TabNine.

                              1. 6

                                I get your point, but I hope (perhaps in vain) that the next generation learns from everything the previous generations have worked to provide. For instance, the almost universal convention of i meaning ‘index’.

                                My vision for next-gen development involves eDSLs and metaprogramming more than machine learning. In this case, perhaps a “comment” sublanguage that is human-readable but could be used to mechanically check the invariants and reasoning that our current comments are attempting to provide.

                                1. 2

                                  perhaps a “comment” sublanguage that is human-readable mechanically check the invariants

                                  I agree with this. In my Tree Languages I try to avoid having any global “comment” node type, and instead only add very specific comment nodeTypes to langauges when necessary, (such as the “todo” comment nodeType in my Grammar Language https://jtree.treenotation.org/designer/#standard%20grammar and a “reference” nodeType in a data flow language which only takes a strongly typed URL). If someone needs to add a different type of comment, there’s no mechanism to do that itself and instead they must bring their problem upstream so we can examine it and either add some new semantics to the language or add a new subclass of comment for that particular category.

                            2. 19

                              I’d take Robert Martin with a grain of salt. While he’s a good writer, he’s also anti a lot of powerful coding techniques, including strong type systems, formal verification, and property testing.

                              Re “make your code describe exactly what it does”, comments are really good for describing things that aren’t what the code exactly does. Descriptive code describes the implementation at the same degree the implementation itself is, and cannot speak outside that implementation. Some comments where that matters:

                              • “While the public method is Shutdown.run, the API call actually happens in RequestBuilder.send via ResponseParser.”
                              • “While this is a performance bottleneck, we’re not at a scale which it matters. If we have performance problems, optimize this first.”
                              • “We’re using the Runge-Kutta approximation with the Fehlburg adjustment.”
                              • “We do not need to call foobar() here for reasons XYZ. Please do not submit a pull request adding it.”
                              • “This is not the event invocation module. You want file ABC. See issue #452 for the naming reasons.”
                              • Any of the 2D data representations here.

                              Sure, comments fall out of date, but that’s less because there’s something wrong with comments and more because programmers never bothered to treat comments with dignity and care. I’ve never seen a truly self-describing codebase, but I’ve seen plenty that needed a lot more comments.

                              1. 2

                                [against] strong type systems, formal verification, and property testing.

                                I use xmobar, which was written in Haskell, which professes all of the above.

                                Every 30 minutes it segfaults on my system. I literally wrote a program to start it, and restart it when it segfaults, because it’s cheaper on my time than figuring out why it segfaults.

                                Those things are part of good code, but they don’t make good code. They don’t guarantee that a system is failsafe, bulletproof, or otherwise stable.

                                1. 7

                                  That’d be a good argument if he made it. But he’s saying they’re all fundamentally inferior to unit testing:

                                  the reason we are facing bugs that kill people and lose fortunes, the reason that we are facing a software apocalypse, is that too many programmers think that schedule pressure makes it OK to do a half-assed job. […]

                                  Better REPLs are not the answer. Model Driven Engineering is not the answer. Tools and platforms are not the answer. Better languages are not the answer. Better frameworks are not the answer. […] I stood before a sea of programmers a few days ago. I asked them the question I always ask: “How many of you write unit tests on a regular basis?” Not one in twenty raised their hands.

                                  1. 1

                                    fundamentally inferior to unit testing

                                    I’d hands down agree with this. If I had to get in a plane with software that was tested, or one with software that wasn’t tested but was written in a very strongly typed language, I’d choose the former every time.

                                    Now, he is NOT against strong typing, and he specifically says that. He’s just saying that unit testing is more important, which I agree with. He is for BOTH, which I am too.

                                2. 0

                                  These are good points, and I appreciate the examples.

                                  anti..strong type systems

                                  Is that true? Source? I never got that impression from his writings, but maybe I overlooked it.

                                  Your examples reminded me of a 2nd place where comments are good (besides temporary todos): links to references. But I don’t think you should put untyped blobs of 2D art or anything like that in source code directly. Instead, have something like “reference http://foo.url”. Almost by definition, comments are the wrong grammar for anything/everything. If something can’t be explained well in code, it certainly can’t be explained well in comments, which are a completely untyped grammar. Instead, perhaps a link to an SVG or some other explanation is the proper channel.

                                  1. 13

                                    Is that true? Source? I never got that impression from his writings, but maybe I overlooked it.

                                    He straight up calls them the dark path. He also says “You don’t need static type checking if you have 100% unit test coverage.”

                                    Almost by definition, comments are the wrong grammar for anything/everything. If something can’t be explained well in code, it certainly can’t be explained well in comments, which are a completely untyped grammar.

                                    I’d argue the exact opposite. Comments aren’t tractable to analyze, but they have infinite expressiveness. Some things we can’t explain well in code because code’s expressiveness is limited by its need to be tractable. Code can only tell us what “is”, it cannot tell us anything else. That’s the price of having something that’s implementable.

                                    1. 4

                                      Comments aren’t tractable to analyze, but they have infinite expressiveness. Some things we can’t explain well in code because code’s expressiveness is limited by its need to be tractable.

                                      I’d disagree with this. Natural language has finite expressiveness, and is also limited by its need to be tractable to analyze. You can’t write only for yourself, but have to write in a way that is actually tractable to analyze by an external reader, who is a finitely limited human, not some kind of magical being living outside of space and time!

                                      Granted, humans are much better at this currently than computers, so the difference can seem huge, to the point where humans can be glossed as having “infinite” ability. But I’m not sure it’s a difference in kind rather than amount. The quantitative difference can even narrow very quickly if you don’t make strong implicit assumptions about your reader. For example, say your comment is written in a C++ codebase in English, and your reader is a strong C++ programmer, but has weak English fluency. Are your comments still infinitely expressive and tractable for the reader to analyze?

                                      1. 1

                                        He specifically says he is not anti strong systems:

                                        I don’t want you to think that I’m opposed to statically typed languages. I’m not.

                                        That being said, thanks for pasting that. Very interesting read. The crux of the article is that you should always be “writing lots and lots of tests, no matter what language you are using!” which i agree with.

                                  2. 15

                                    This is some of the worst advice I’ve ever seen with respect to comments. If someone followed these rules, their code wouldn’t pass my code review.

                                    Much better advice: do what is necessary to communicate understanding of code to others reading it. If comments are required, then do it. Whether the language is expressive enough or not is immaterial. Reality dictates.

                                    1. -2

                                      It’s forward looking. Comments should only be temporary. They are code smell. Temporary todo comments are okay. Comments that are links to references (which then can be in a language more appropriate to an “Explanation”) are okay.

                                      I highly recommend reading Clean Code if you haven’t before.

                                      Untyped blob comments are by definition a terrible grammar with infinite entropy and no tooling help and should be used very sparely.

                                      1. 9

                                        This is the most ridiculous take on commenting I’ve ever seen. If this is what’s in Clean Code, then it only reinforces my opinion that reading Bob Martin’s writing is a complete and total waste of time. (Which I initially formed by trying to read his writing.)

                                        I don’t care about being “forward looking.” I care about whether myself and others can read my code and understand it. Comments are one of a few critical tools that help make that happen. Removing that tool because of some ideological nonsense about it being “untyped” and it therefore possibly being incorrect is one of the most crazy cases of “don’t throw the baby out with the bathwater” that I’ve ever seen.

                                        1. -2

                                          my opinion that reading Bob Martin’s writing is a complete and total waste of time.

                                          My god sir, stop spending time reading my silly comments and go get yourself a paper copy of Clean Code! It will be worth its weight in gold, if you care about improving your skills.

                                          don’t throw the baby out with the bathwater

                                          I do live in the future a bit, as my time is spent designing new languages. But I stand 100% by my advice, if you’ve mastered most of the other aspects of programming. And perhaps that’s too much of an ideal, and indeed I almost always do provide an escape hatch in my languages to not throw the baby out, as you put it. But if you are resorting to comments other than for a very small few categories of buckets such as 1) temporary todos 2) links to references, you are doing something wrong. Perhaps it’s using the wrong language, perhaps it’s not understanding all features available in the language, perhaps its bad identifier names, perhaps its functions that are doing more than one thing, perhaps its not writing tests, perhaps its function bodys that are too long, perhaps its because your readers dont understand the programming language, perhaps its flag arguments, perhaps its too many parameters, perhaps its side effects…and on and on….There should never be a reason why you need to describe something in an undefined implicit grammar for a “human machine”. I 100% stand by this and have an immense amount of data on my side (I’ve read and worked on code and worked on language design in probably more languages than nearly anyone on earth at this point, ftr, so it would take some really novel evidence and data, and not some exposition, to convince me otherwise).

                                          1. 6

                                            Your experience is so far removed from mine (and many others that I know) that there is just no way we are going to see eye to eye. It is a waste of my time to get into it with you and give you data. You throwing your experience around is also really off putting to be honest. Others have plenty of experience too and strongly disagree with you, like I do. As I said, your methodology wouldn’t pass my code review. Not even close.

                                            1. 0

                                              that there is just no way we are going to see eye to eye

                                              That’s fine.

                                              You throwing your experience around is also really off putting to be honest.

                                              I know I was afraid of that, I just wanted to put out that to convince me otherwise would take lots of data, not argument, since my corpus is quite large.

                                              Others have plenty of experience too and strongly disagree with you

                                              That’s fine. I work on the future looking at data from the past to find new things and if everyone agreed with me I wouldn’t be inventing anything novel.

                                              As I said, your methodology wouldn’t pass my code review. Not even close.

                                              And I think it’s good that you take code reviews seriously. I work on different types of things where the goal of good language design is that you’d never have to write a comment to explain what the heck is going on, as the language should allow for it.

                                              But again, thank you for that chat (and I would read Clean Code. It’s a fantastic book!)

                                            2. 5

                                              if you are resorting to comments other than for a very small few categories of buckets such as 1) temporary todos 2) links to references, you are doing something wrong

                                              I find these kind of nuance-less “strong” opinions very tiresome. Observational evidence clearly shows that there are many highly productive programmers working on high quality code bases which use comments in ways other than you described. Indeed, the entire concept of Literate Programming is pretty much the exact opposite of what you’re advocating.

                                              Sometimes, there is more than one path to excellence. And what works for one person, might not work so well for another. Quite frankly, every time I see someone way “do X or you’re doing it wrong” – where “X” is a reasonably popular practice – especially without showing any understanding of why people do “X” (other than “they’re stupid” or “they’re wrong”) my response is something along the lines of “oh, he just hasn’t bothered to actually understand why people are doing the thing he’s so aggressively opposed to”. Turns out, that most of the time people are not complete idiots, and have actual valid reasons for doing the things they do (both in software dev and outside of it).

                                              I 100% stand by this and have an immense amount of data on my side

                                              You can’t say something like that and then not show your alleged “immense amount of data”.

                                              1. 0

                                                Literate Programming is pretty much the exact opposite of what you’re advocating.

                                                I love LP and I would say Literate programming and no comments are not opposed. In fact, I would say the opposite. Great programming languages should be self-documenting and readable. IMO we are barely scratching the surface of great programming languages, and my research is focused on this.

                                                just hasn’t bothered to actually understand why people are doing the thing he’s so aggressively opposed to”.

                                                What are you talking about? I am clearly demonstrating at least 2 buckets of categories for why people are commenting code (todos and references) that I think should always be there in languages for comments. I am also very open to more buckets. I am against again type of “# or // or /* “ syntax however, as that just shows the language designers have put little thought into why people are using comments and what they are using them for.

                                                You can’t say something like that and then not show your alleged “immense amount of data”.

                                                Well, for starters, the OP should read Clean Code. I’ve read that book probably 5 times by this point (and about 500 other programming books – Practice of Programming, Pragmatic Programmer, Pattern on the Stone, ANTLR 4 Definitive Reference, Learn you a Haskell, SICP, Bray’s Intel x86 assembly book, Mastering Regex, Programming Collective Intelligence, Data Structures + Algos equals Programs, are some good ones to start with). Here are 19 new languages I’ve designed https://github.com/treenotation/jtree/tree/master/langs. One of those took me an hour and sat at #1 on Lobsters for 2 days. We’ve also built the largest database of computer languages in the world by far, and will be releasing it soon, here: https://github.com/treenotation/cldb.

                                                Turns out, that most of the time people are not complete idiots,

                                                I never said this and don’t think anything of the sort. I just think the OP’s comments were a bit sophmoric (nothing wrong with that, we all go through phases of that). The OP started his response with “This is some of the worst advice I’ve ever seen with respect to comments”. That would be like me going up to Lebron James and saying “your basektball tips are some of the worst I’ve ever seen”. As Guido once said to me ‘When your reputation precedes you, I might answer your questions’. I think OP has a long way to go before I might take his opinions seriously over Bob Martin’s.

                                      2. 7

                                        One loop: index.

                                        Two loops: index, jndex.

                                        1. 1

                                          Generally you’d be iterating through collections of 2 different types, or 2 orthogonal directions. So you’d want something like manufacturerIndex, modelIndex.

                                          1. 2

                                            What if you’re iterating twice through the same data?

                                            For example, day 2, part B of 2018’s advent of code is essentially the following problem: Given a list of strings, all of the same length, find the unique pair that differs by one character in one position only. (That such a pair exists and is unique is promised by the problem statement.)

                                            Pretty much everyone will solve this by doing:

                                            for (int i = 0; i < len; i++) {
                                              for (int j = i+1; j < len; j++) {
                                                // check the condition, return
                                              }
                                            }
                                            

                                            Is the time spent coming up with longer loop variable names worth it, when you could call them i and j and maybe comment that the condition being checked is commutative so we’re essentially checking a symmetric matrix and can start the inner loop at i+1?

                                        2. 6

                                          What language features are you thinking of that can explain why the code was written one way instead of another?

                                          As far as out of date comments go, it’s a code review problem.

                                          1. -1

                                            If you can’t explain in the language itself, then choose a more appropriate language for an explanation (Diagrams, for example) and add a comment with a link to that.

                                            As far as out of date comments go, it’s a code review problem.

                                            No. When you write a comment you are also making up an ad hoc, implicit grammar on the spot, with no tooling. Grammars are important to help people and tools communicate. You are asking a code reviewer to infer what the grammar is in a comment, to parse that example, and then run checks in their head to make sure nothing broke. That should be obvious why that is a big problem.

                                          2. 5

                                            Instead of comments, make your code describe exactly what it does. useLongVariableAndMethodNames. Never have single letter variables(Yes: even use the word “index” instead of “i”). Put the time you would spend writing comments into better tests and code.

                                            How about this as a guiding principle; do what needs to be done for people to understand your system.

                                            The key bit about this is that there are people on the other side of this equation, with different ways of understanding and picking up information. It’s all good and well for me to say, well, my unit tests describe the behavior of the system, but if people struggle to pick up information quickly that way, it’s not an efficient means of documenting the system (though it continues to serve a purpose in partially enforcing the behavior of the system).

                                            I like the useLongVariableAndMethodNames technique - I also don’t think it works for every situation, and in those times, you need other tricks.

                                            1. -1

                                              How about this as a guiding principle; do what needs to be done for people to understand your system.

                                              I like the intent behind it, but generally comments to me are a code smell that something has been done wrong. So I like the principle better: “if you are resorting to comments figure out what you are doing wrong”. But as there are dozens of things (at least) you have to master to avoid resorting to comments, switching to temporary comments (todos) is fine.

                                            2. 3

                                              I have a program where the following three lines of code are preceded with a block comment:

                                              if not location.path:match "/$" then
                                                return HTTP_MOVEPERM . uurl.escape_path:match(location.path .. "/")
                                              end
                                              

                                              The context is a web server, having gone though a path were it ends up pointing to a directory. Now, can you explain why this code exist? And why do I even care to check this case? If you can answer this, then maybe the comment block that precedes this could be removed.

                                              1. 1

                                                Two ideas for how you could improve this. 1) is to create a long method name that explains what/why something is happening. 2) is to add a temporary todo comment.

                                                Very rough pseudocode:

                                                # todo We had some bad links that pointed to an invalid url. Keep this here until those are all gone.
                                                this.redirectBadLins()
                                                
                                                redirectBadLinks()
                                                 return HTTP_MOVEPERM . uurl.escape_path:match(location.path .. "/")
                                                

                                                I suggest reading Clean Code though, does a message better job of explaining great practices than I can.

                                                1. 5

                                                  You are partially correct. On the server, it’s not a bad link—it does lead to the proper resource. But a close reading of RFC-3986 reveals that <http://example.com/foo> and <http://example.com/foo/> have to be treated as two separate URLs. Fine, but I can’t control what links people use. And without the trailing ‘/’ the path merging rules break (section 5.2.3).

                                                  You may counter that a comment in the form of -- see RFC-3896 sec. 5.2.3 is enough, but not really. Or perhaps a pointer to document elsewhere in the repository, but that’s another file that needs to be maintained along with the code. You might be fine with that, I’m not.

                                                  Another aspect of comments is working around bugs in libraries. It’s a sad fact that not everyone gets to use open source and fix every bug they come across in third party code. But I have a project that is littered with comments about working around bugs in a proprietary third party library that we have no access to the source code.

                                                  Oh, I found another example of a good comment in come code I’ve written (not the one dealing with the proprietary library):

                                                  /*--------------------------------------------------------------------
                                                  ; Basically, if g_poolnum is 0, then idx *has* to be 0.  That only
                                                  ; happens in two cases---when the program first start ups, and when the
                                                  ; program has received too many requests in a short period of time and
                                                  ; just gives up and resets back to 0.
                                                  ;--------------------------------------------------------------------*/
                                                  
                                                  if (g_poolnum == 0)
                                                  {
                                                    idx = 0;
                                                  }
                                                  

                                                  Can the variables name be better? Perhaps. Am I going to wrap this up into a function like reset_pool_if_number_left_is_zero()? No. It would be a) one more bloody function to test, b) only called from one location in the entire code base. Not worth it to me (not a fan of the large number of small functions).

                                                  I think we’re going to have to agree to disagree on your view of comments.

                                                  1. 2

                                                    In the limit, method names have exactly the same problem that comments do: they are written in natural language and can become out of sync with what the method actually does.

                                                    I could have answered that “why” posed above (when eventually I parsed the regex: sunday morning brain), but only because I’ve encountered the problem before. If foo matches a directory name on the server and you have (say) an index.html file inside it, if you serve the index instead of first doing the redirect then any relative links in it will be resolved incorrectly by the browser

                                                    1. 0

                                                      In the limit, method names have exactly the same problem that comments do: they are written in natural language and can become out of sync with what the method actually does.

                                                      This is true in theory, but in practice I find it much less likely, if you are following other best practices (like having short function bodies, functions that do what they say and only what they say, functions that do one thing, etc). But it does indeed happen, and when I see it occur I’ll drop a “todo This fn name is out of date”