In Search Of The First Comment

Are you writing your code for humans or computers? I wasn’t there, but my guess is that at the dawn of computing, people thought that they were writing for the machines. After all, they were writing in machine language, and whatever bits they flipped into the electronic brain stayed in the electronic brain, unless punched out on paper tape. And the commands made the machine do things, not other people. Code was written strictly for computers.

Modern programming practice, on the other hand, is aimed firmly at people. Variable and function names are chosen to be long and to describe what they contain or do. “Readability” of code is a prized attribute. Indeed, sometimes the fact that it does the right thing at all almost seems to be an afterthought. (I kid!)

Somewhere along this path, there was an important evolutionary step, like the first fish using its flippers to walk on land. Comments were integrated into programming languages, formalizing the notes that coders of old surely wrote by hand in the margins of the paper first-drafts before keying it in. So I went looking for the missing link: the first computer language, and ideally the first program, with comments. I came up empty handed.

Or rather full handed. Every computer language that I could find had comments from the beginning. FORTRAN had comments, marked by a “C” as the first character in a line. APL had comments, marked by the bizarro rune ⍝. Even the custom language written for the Apollo 11 guidance computers had comments — the now-commonplace “#”. I couldn’t find an early programming language without comments.

My guess is that the first language with a comment must have been an assembly language, because I don’t know of any machines with a native comment instruction. (How cool and frivolous would that be?)

Assemblers simply translate mnemonic names to their machine instruction counterparts, but this gives them the important freedom to ignore anything starting with, traditionally, a semicolon. Even though you’re just transferring the contents of register X to the memory location pointed to in register Y, you can write that you’re “storing the height above ground (meters)” in the comments.

The crucial evolutionary step, though, is saving the comments along with the code. Simply ignoring everything that comes after the semicolon and throwing it away doesn’t count. Does anyone know? What was the first code to include comments as part of the code itself, and not simply as marginalia?

105 thoughts on “In Search Of The First Comment

  1. First languages were machine languages, and programs were first written on paper. Comments in mashine language are even more important than in moderl languages, mashine language is so cryptic to humans that we need comments to undarstand. First programs were written on paper and comments we just notes on margins. We can say that comments are older than languages. :)

      1. She likely had background in mathematics, and proofs in mathematics had lot of text explaining which theorem is involved where so that **people** can assert whether the proof holds. Possibly that’s where comment are from.

        I wouldn’t be looking for comments in a program punched onto cards, except for things like job description, but (as shown in the nam-IP museum I just visited), people back then would extensively document their process before putting it into production. Part of the job would be done by the machines (sorting cards), and another part by operators (store stack 1, feed stack 2 in machine B).

        1. I wonder if there’s any database/library of mechanical loom cards to see if there are any comments written on them. While they aren’t quite “programs” it could still be a viable choice of earliest comment.

        2. Ada Lovelace’s background is extensively documented, there’s no “likely” about it.

          However, engineering and scientific practice was to document work and design mothodology in a personal notebook or project logbook… see in particular Grace Hopper’s description of finding a bug in the early computer she was working on.

        3. “She likely had background in mathematics”

          And how! Her mother was Anne Milbanke who was privately educated by a former professor from Cambridge University in, amongst other things, science and mathermatics. Ada’s father was the poet Lord Byron and he and Anne separated on such acrimonius circumstances that Anne kept his portrait behind a curtain and insisted that Ada’s education was similar to her own and definitely didn’t encourage the pursuit of literature. Ada became a pretty good mathermatician in her own right, though in later life she did attempt to apply it to gambling on horses (guess how that went). If only Babbage had managed to build an analytical engine.

        4. On the contrary, when I programmed in Fortran, on 80 column Hollerith cards, in 1973, some of the cards were entirely comments, not just as dot matrix print across the top of the card, but also punched.
          After all, it was in the program listing that the comments were needed.

          Our batch jobs had a couple of job control cards in front, telling the executive to compile and run. They were just a few obscure macros, inscrutable to us. The operator stacked several card decks in the reader, separated by a blue card so that she could quickly split the decks again when lifted from the output hopper.

          Even as a secondary school student, in 1971, when submitting BASIC programs on pencil marked cards, where the first card had to be a “Scratch” instruction to clear memory of the previous job, this youg’un felt compelled to utilise the fact that any following text would be ignored, to write “Scratch when it itches”
          Even before they become purposeful, comments can not be suppressed, even on punched cards, it seems.

          It is interesting that comments predate electronic programming, but not surprising. I have programmed in assembler for 49 years now, and the need is greater there than in a ‘C’ program or shell script.

          1. I hadn’t thought about the possibility that some instructions Would have to be at the start of the card, but would make the reader ignore everything beyond some place. Interesting.
            Was the ’73 FORTRAN program punched manually ? or were there by any chance an operator who would have been instructed to « Type everything written on the listing you’re given. » and wouldn’t try to figure out whether some lines Were comments and could be skipped?

      1. PypeBros wrote: “Was the ’73 FORTRAN program punched manually ? or were there by any chance an operator who would have been instructed to « Type everything written on the listing you’re given. » and wouldn’t try to figure out whether some lines Were comments and could be skipped?”

        It was at uni, and over in the electrical engineering building we students had access to two desk-sized keypunch machines with automatic card feed and keyboard. Fed from a stack of blanks on the right, each card was punched behind glass on the other side of the keyboard, and they accumulated to the left in an inverted deck. Through a door in a half glass room divider there were two punch card operators with a machine each, and they could be asked to do the work. They would not have skipped any text submitted for transfer to card.

        The ICL1901 mainframe was 24 bit, and its ferrite core memory would have been very limited by today’s standards. Neither compilable source nor comments would have been memory resident at run time, I’m sure.
        The concept of “comments stored with code” extends mainly to the punch cards and the printed listing. The card reader swallowed many cards per second, and the line printer hammered away seconds behind, so comments would have resided in memory briefly before being superfluous in a precious resource.

        The HP2100A minicomputer we had in EE had 16 kB of 980 ns ferrite core memory, as 8k 16 bit words – that’s 8k instructions minus any data space you needed, and the tape reading boot loader occupied about 64 words, IIRC. (I only overwrote that once, so had to load it by hand via the front panel switch register.)

        An aside: They were the days of ascii art. One night, after the operator had gone home, I wrote a short program in PLAN, a low level language which gave me direct control of the peripherals, including card reader and line printer. Another student had found massive ascii art card decks in the computer room, but had no way to stitch one and a half 80 column cards into a 120 column printout. It took two goes to get it right in an unfamiliar language not taught, but I still have somewhere, printouts of Obelix, and The girl on the stool. The computer manager did ask next day what we got up to with the mainframe, since the disc drives held all the student records and whatnot. They were more innocent times, without a doubt. I’m sure we locked up before going home.

      1. if Knuth & Pardo’s paper on the matter is anything to go by, you’ve already mentioned the answer – Fortran I. To quote:

        “The chief innovations [of FORTRAN I] are: (1) Provision for comments: No programming language designer had thought to do this before! (Assembly languages had comment cards, but programs in higher-level languages were generally felt to be self-explanatory.)”

        – p89, STAN-CS-76-562_EarlyDevelPgmgLang_Aug76.pdf (archived at bitsavers)

      2. What do you mean by “stored with the code”?

        If you were programming in raw machine language, you wrote the whole thing out on paper, and then punched an *object* tape or deck. The only “source code” was the paper version, which would have had comments all over it, and which I’m sure was usually kept around (“stored”) and even amended. Compilers don’t put comments into the object code, so it seems to me that “stored with the code” best describes that piece of paper.

        1. Ah, yes, hand assembling, then inputting the raw binary or octal opcodes. (Hexadecimal, a backward step, was only introduced around the mid 70’s for display economy, as a byte could be displayed on two 7 segment display digits instead of 3 for octal.) I’ve only hand assembled for the TMS9900, as late as 1979, having no assembler for the SBC I bought for home use. So yes, the source existed only in handwritten form, with hand coded opcodes, and a few comments.

          Built a keyboard from a kit, designed my own keyboard encoder, using diodes and a few transistors,and built a 25 x 40 character terminal from a kit and a small B&W TV, feeding the composite video in after the front end, via a BNC socket on the back.

      3. Its not so much a ‘mindset’ as it is a method to do with the technology. Comments are always ‘taken seriously’, back in the time of paper source code moreso than modern languages in many cases. The original computers didn’t have the storage capabilities that we’re used to today. Programs were fed in 1 at a time and directly filled the memory and registers with instructions and data. Answers were computed and output to the one available.

        You’re essentially looking for when computing had the added convenience of online storage of programs that didn’t have to be fed in individually. At that point the comments had to continue to be stored along with the sourcecode still, just the storage method had changed.

    1. Yes and No… The “first” programme I wrote was on punch-cards. Comments were the flow chart used to come up with the programme. The next programming I did was Sinclair BASIC and with 1k of RAM, there was no space for comments! :D

    2. Some time back I discovered a function name in C could be 255 chars long.

      char ever[2] = “;;”;
      int color_green 0x00ff00;

      Build_the Start_Button_For_The_Init_Page ( int and_use_this_color ) {…

      Build_the Start_Button_For_The_Init_Page ( color_green );

      for(ever) {xyz}

      It took some imagination but the whole program was the comment. The boss wasn’t happy. He wanted:
      Bsb (#00ff00); /* Create a start button color green */

    3. The first languages were arguably written almost prose style because they were written for other people to understand what exactly the instruction logic was doing. It was only then that someone turned the cranks on the first mechanical calculators.

      It was only later that electronic calculators became the norm, and the way you interfaced with those computational machines was through punch cards. There was no room on punch cards for comments, only the line numbers and hand written page numbers in case the card stack got dropped.

      Then, once we were able to be more verbose with machine instruction with the introduction of teletype-like interfaces and VDRs, we could once again write code for other humans to read. The complexity of the new code then required ever increasing line numbers of comments. The first professor that taught me how to code more than a few lines also taught me the value of documenting what I was doing. That not only included comments in the code files as I wrote it, but also parallel hand written documentation of the logic and thought processes in case the original code was ever lost to malfunction or human error. The add-on effect is that you also document what you’re doing with computer configurations so the person that comes later, which may even be yourself, knows WTF you did with the printer to get it working properly the last time it mangled a PostScript file (which happened way more than it should have – it was a specific bug in a program that mangled the PS header which required manual repairs to the files).

        1. Didn’t Ted Nelson in “Computer Lib” promote APL? We should have listened to him.

          I think he thought well of two other languages, Trac and I forget the other.

          And you weren’t supposed to mention Trac without a copyright symbol.

          1. In mid 1977 BYTE magazine went APL crazy for a time, and ran an 3-part article on how to write a tiny APL interpreter by following pseudocode and flowcharts. They ran a contest for users to submit their own microcomputer implementations, but as far as I know from searching subsequent issues on archive.org it appears to me no-one did and it sunk without a trace.
            Although it is plausible the VideoBrain APL/S (using the F8 CPU) could have originated from it.

    1. I actually learned APL in school, and it is indeed crazy. The syntax is tremendously terse, uses a large number of special symbols, and complicated programs are unreadable even to people who know the language.

      The symbol shown above is named “lamp”, shining light on the problem. The original symbol had the circle above the monolith (sort of like the character “8” with the base shaved off), representing a lamp on top of a hill, but this somehow morphed into the one shown above.

      The language has some really convenient notation for vector and matrix operations that I’m still waiting for in modern languages. Function calls don’t count.

      For example, the notation A +.* B, the “+.*” notation means “multiply the elements together, then sum over the results” which is the inner product of 2 vectors. The thing is, the “+” and “*” could be ANY two dyadic operators, even the null operator, which is wildly convenient once you get used to it.

      …but sadly, not available in modern languages that I know of.

  2. Now try to find the first “first” internet comment. That is, a comment on the internet where the whole comments content is just the word “first” as if being the fastest one to post a comment is some sort of success.

      1. It might be difficult to define what is a comment. One of the first uses of the internet was likely to send email messages across different systems, as well as extend other methods of communication that had already existed on individual time-sharing systems. If I send an email to a group of folks and ask for their thoughts, do their replies count as “comments”?

  3. Never really thought about it but I don’t think I’ve ever seen any language that without any special IDE extension had the feedback between comments and code that .NET languages allow. Look at the MSDN entries for C#, you can build that for your code base using comments in C# with a basic understanding of xml. Other languages I have used have had similar available but it was as a bolt on feature instead of something tightly integrated.

    1. Doxygen dates back to the same year as VS.

      Philosophically the “bolt on feature” mentality is some sort of unixoide style of building things while those living in the windows world prefer more the monolithic style.

      That said, the 3-slash-comments in VS are an easy + fast way to build a help system around the source code and “integrate” it into the IDE. Just learn some macros and code completion does a good job.

  4. DNA seems to have a lot of non-coding sequences. There are well defined runs of code that direct the construction of proteins and such, but also a lot of “junk” DNA (actual term – google that) with no obvious use.

    Perhaps that’s the first usage of comments kept in code?

    1. The key word here is “seems”. We humans have such a habit of assuming anything we don’t understand is ignorable garbage. We’re usually wrong about that, sometimes catastrophically.

    2. I’ve seen at least one article claiming that some function is being performed by a portion of DNA previously believed to be junk. I expect that such discoveries will continue. Given the erratic nature of evolution, it is likely that some portions of DNA serve no purpose beyond being a placeholder.

  5. The first comment was actually written on a punch card since the machine doesn’t care about what the card looks like. It was from here that the value of comments was recognized. When there was enough storage space for more than just binary programs, then they added the ability to write comments.

    1. That’s marginalia. When was the comment part of the language? Because that enabled them to be stored along with the code — in the same format.

      Comments in Fortran were lines starting with “C” — and these were _in_ the punch cards, not on them.

      Was Fortran the first?

      1. You can read more into that comment. The first computers literally had no extra space in memory to store comments. However, once you had an external data storage such as punched cards, which made storage space abundant, you could also include comments as computer-readable data on the cards. You could then show the comments on printouts, and you’d also define a method of separating the data that the computer cared about vs. the comments that humans cared about. Often this amounted to putting each into its own set of predefined fields (ranges of columns on the cards).

      2. Only a few programming languages precede Fortran, but I don’t have the complete syntax/bnf for those.

        I don’t think Short Code (also called Brief Code) from 1949 had comments support, just based on it terse (memory saving) nature.

        Speedcode (or Speedcoding) from 1953 was the first of the high-level programming languages, while I don’t have the complete syntax or bnf, this may have supported comments, given that it was supposed to be aimed at people rather than machines (although memory is still tight).

        PACT I from 1954 is another contender, although again I don’t have the syntax/bnf. This was a compiler aimed at producing low memory overhead code, so it’s possible it could support comments (since comments won’t effect the resulting binary size or memory usage).

        Wiki links in case somebody wants to dig deeper:

        https://en.wikipedia.org/wiki/Short_Code_(computer_language)

        https://en.wikipedia.org/wiki/Speedcoding

        https://en.wikipedia.org/wiki/PACT_I

  6. I was taught many years ago that it is good practice to comment every line. That was with assembler. I think it can be even more important these days with the likes of C where ‘clever’ programmers seem to think using perverse constructs without comments where a full understanding of the way the complier interprets the line is required is good. Sorry, cool. Explain in comments and use parenthesis to make the operation clear. Comments also allow you to compare what you’ve written with what you wanted to do.

    1. Oddly enough I’ve only ever seen that antisocial C commenting behaviour with older programmers, who think that short code means better code, it also goes with using as little whitespace as possible, and absolutely no spaces in variable calculations.

      1. I had that too. I think people who have only ever programmed in C, think it’s the only language that matters and that everyone should be at their level. We all have to learn and studying well commented programs helps both the novice and the experts modifying code later down the line. There’s no such thing as ‘self commenting code’ no matter how much the college tutor wants it.

      2. “Good code doesn’t need comments” is useful as a thought experiment and as an aspirational principle, but yeah it’s not something that anyone should take literally.

        When writing comments I often ask myself how I could change the code to make the comment unnecessary, and that often leads to better code. But no amount of code clarity will replace the ticket number and short summary of the customer support call that led to a non-intuitive branch condition.

        1. I agree with everyone here on the importance of generous use of comments. In my opinion, it is impossible to have too many.

          If nothing else, I have discovered that even “obvious” constructs in my code may appear cryptic to me when the source is reopened a decade later for modification or a fix.

          Having to reverse engineer something I wrote myself is a waste of time when the courteous me of the past can simply explain what’s going on with a line or two of comment.

          By the way, as an old-school guy, all of my functions or subroutines are headed with a text block explaining what it does, what the input and output parameters do (including their data types), and commentary on the author, date, and revision history.

          Does anyone still do that?

          1. You will love `rust`. There you clearly instruct the compiler what data types you are working with. Example (comes from https://doc.rust-lang.org/book/ch03-03-how-functions-work.html )

            “`rust
            fn main() {
            let x = plus_one(5);

            println!(“The value of x is: {}”, x);
            }

            fn plus_one(x: i32) -> i32 {
            x + 1
            }
            “`

            https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html tells about _documentation comment_.

            Keeping track of who, what, when and why is done with `git` VCS.

            Consider it _good school_.

          2. That was what I actually got called out for – putting a header on a class to explain what it did rather than MakeTheNameDescriptive (a practice I find falls short for classes).

            He also said I should make 1 a constant in n = n + 1. Fun times! :)

        2. its good in principal provided you aren’t doing anything so esoteric that it warrants explanation. you can also write code so badly that its practically unreadable. one should be able to write readable code before declaring it as good as comments actual. i’ve written code where the comments don’t even make sense.

    2. ugh, in asm i understand comments every line, because your variables are all living in registers…it can really be a bit of detective work to associate registers with their logical values.

      but in C, comment every line is harmful.

      ind += 5; /* increment the index by 5 */

      i can’t tell you how much code i find like this, and i’ve begun simply removing the comment as an improvement all on its own. i’m a *huge* fan of comments. especially to explain something that isn’t clear, or to present historical reasoning for something that seems stupid, or to document an interface.

      but useless comments are harmful. they take up vertical space so it’s hard to find the code that does anything, and they double the amount of reading you have to do — you read the comment because it seems like it will be useful, and then you have to read the code to see if the comment is even accurate. reading is the single most important task when programming, and comments should help you read not deter reading! plus, if your comments are so verbose then maintaining comments can become a chore on its own, and that chore goes undone and then your comments are now out of sync with your code. it can become severely pathological.

      as a rule of thumb, the ideal commenting style is to have comments at the top of any decently complicated function, but rarely in the body of functions. if your function is so complicated that you have something unintuitive to explain inside the function, you should probably factor. if your function is so intuitive it doesn’t need comments, don’t make some. i see this so much:

      /*
      * accum_entry()
      * input: an entry to accumulate
      * return value:
      */
      void accum_entry(struct entry_rec *e)

      i just want to tear my hair out when i see that. the function is perfectly self-documenting, those comments are 100% redundant. you should be reading the function, but instead you’re reading the awful comments because they take up so much space, command so much attention. to top it off, if accum_entry() does something tricky, maybe maintains a cross-indexed hash table or something, the comment before the function should explain that! but if you’re using this pro-forma commenting style, then *it never does*. the fact that you’ve satisfied the formal requirement to have a useless comment invariably deters people from providing the useful comment about the surprising indexing mechanism.

      this was one of my big complaints working on raspberry pi. when i say the libraries were poorly-designed wrappers, i mean i found a bunch of code like this:

      /***********************************************************
      * Name: vc_cec_set_passive
      *
      * Arguments:
      * Enable/disable (TRUE to enable/ FALSE to disable)
      *
      * Description
      * Enable / disable CEC passive mode
      *
      * Returns: 0 if successful, non-zero otherwise
      ***********************************************************/
      VCHPRE_ int VCHPOST_ vc_cec_set_passive(vcos_bool_t enabled) {
      uint32_t param = VC_HTOV32(enabled);
      int32_t response;
      int32_t success = cecservice_send_command_reply( VC_CEC_SET_PASSIVE, &param, sizeof(param),
      &response, sizeof(response));
      return (success == 0)? response : success;
      }

      an 11-line comment that literally doesn’t provid eanything you wouldn’t’ve intuited immediately from the name of the function. there’s an almost identical 9-line comment in the header file that provides only a little more information…so now i’ve read 20 lines of comments and still don’t know what passive mode is. and the thing is, look at the code of the function…it’s boilerplate API wrapper, it doesn’t do anything, you can compress that code any which unreadable way and it won’t suffer any, the only information you could get out of it is the knowledge that vc_cec_set_passive() at this level is the same as VC_CEC_SET_PASSIVE at the wrapped level.

      i did eventually find the only useful comment:

      //The following 3 commands are used when CEC middleware is
      //running in passive mode (i.e. it does not allocate
      //logical address automatically)
      VC_CEC_POLL_ADDR,
      VC_CEC_SET_LOGICAL_ADDR,
      VC_CEC_ADD_DEVICE,
      VC_CEC_SET_PASSIVE,

      so in passive mode, userland can allocate the logical address. that’s useful information, and it wasn’t exactly hard to find, but the useless comments hindered that search. but it doesn’t actually tell me the information i want. i want to know, in active mode, how is the allocation performed? when is it performed? does it conform to the CEC standard? does it work? can the CEC bus-monitoring interface see the active allocation, or is it hidden? and then the really harsh ones: in passive mode, WHY DOESN’T IT WORK? why does releasing the logical address cause it to assign a new one at random? why is polling so unreliable?

      i have so many questions and there are so many comments, but 99% of the comments are pro-forma comments that just take up space and obscure knowledge, diffusing redundant copies of superficial knowledge across my screen. these pro-forma comments represent a serious investment of technical labor that wore people out who could have been writing useful documentation instead. it’s a frickin crappy wrapper library…i would’ve invented a few macros so that the whole thing could be specified in a couple dozen lines of source code…factor it until the fact that every interaction is the same becomes absurdly obvious. but instead they blew it up into 1365 lines, mostly redundant comments, and the code itself is all redundant code. so if you do want to go audit this thing for bugs, there’s a huge surface when all it is is the simplest functionality. the wrappers don’t need documentation, the underlying interface that they wrap needs to be documented and *that* didn’t happen.

      when one useless thing got done and the useful thing went undone, i think it’s fair to say that doing the useless thing got in the way.

      1. Greg, did you consider the counter-argument, that maybe you should buy a larger screen to regain vertical space? Maybe with an arm that can rotate, so you can use portrait mode?

        In my experience, people who are mad at the existence of documentation do not read that documentation, and often they program from memory, which is fallible. And all humans believe their memory to better than it is! You spend a lot of words hammering at the case you want to make, but I still don’t see a single good reason not to have a comment on incrementing an index.

        The redundancy, like the redundancy in your comment, is for clarify; if the code is clear but has a subtle bug, how would you know? Not by looking at the code, you’d have to know by thinking about other things that are somewhat distant from the line of code in question. It is through the redundancy that you can look at the code, consider what it is supposed to do, and consider the range of inputs for which it actually does that. Bugs can result from simple mistakes, so the whole complaint falls down.

        1. i’m not mad about documentation, i’m mad about pointless comments. having more vertical space isn’t the problem. i think you didn’t look at or understand the extremely poor quality of the comments i shared as examples? pi foundation, for example, really did provide useless boilerplate comments, and really did not provide documentation.

          “Not by looking at the code, you’d have to know by thinking about other things that are somewhat distant from the line of code in question.” as you say, it is a struggle to keep enough things in your head at once. redundant low-value information makes this harder, no matter the size of your screen.

      2. “if your function is so intuitive it doesn’t need comments”
        “void accum_entry(struct entry_rec *e)”

        So, that might be intuitive to you, but it’s not intuitive to me what this function is doing. I’ve been bitten too many times to be make assumptions about what this function does, there is no clear indication if this is for reading or writing data. I agree that the comment in your example is poor (well, more mediocre, it’s not wrong, it’s not harmful in itself), but it did add value by letting me know that ‘e’ was an input, and not part of a convoluted output mechanism, I also got that ‘accum’ in this context is short for ‘accumulate’.

        I agree that bad comments are harmful, but so is bad code. Deleting comments isn’t the right solution to bad comments, the right solution is better comments.

        I would much rather work on (or create) a code base with that had every function commented (even the simplest setters/getters), than work on a code base with very sparse comments…

        Another factor is the diversity among programmers, we grow up in different eras, we get different training, we start out on different languages, we have different experience levels. I want the undergrad intern that’s going to be on my team for 6 weeks to be as productive as possible, as well as seasoned programmers, I want to be able to onboard junior hires quickly – well commented code really helps.

        1. you’re being obtuse. you know as well as i do that accum_entry(struct entry_rec *e) is most likely one of 3 trivial linklist append idioms that you’ve seen a dozen times.

          the thing is, this knowledge of its extraordinary simplicity is harmless in the case that it proves to be incorrect! if it is well-written and not buried in pointless comments, then all of those idioms are 5-10 lines of code. you can glance at it and in an instant know if it has astonishing contents. but i’ve seen cases where it is the 5 line linklist insertion idiom with literally 50 lines of comments, and one interesting line of code that does something quite astonishing! you can’t find the astonishing code because there’s 50 lines of comments that don’t tell you anything.

          and, again, in this case, the poor quality comment literally doesn’t tell you if it does anything astonishing or not. all it does is waste space without telling you the things you might need to know, only telling you things you could tell already.

          1. To tell the truth, I don’t remember ever seeing “accum_entry(struct entry_rec *e)” before you used it in your example above, I don’t know what it does (seriously). The first hits for ‘accum_entry’ on google search are something completely different. Putting double quotes around the search term gives 3 results, this page with your example is one of the results (neither of the other two results are related to your function).

            Your assumptions around tribal knowledge means that your code base is hard to work on and takes more time to spin up new developers. Now instead of working the assigned task, people are busy reading code trying to figure out what the boiler plate is doing. You save 5 lines, but now development costs more. Given those lines of comments would probably never change, and they do help (“help” a little, they could be much better), was there really a saving in deleting them? The biggest cost from keeping the comment would be if somebody spent five minutes improving it later on.

            When I develop software, I care about how quickly I can spin new folks up, I care about how much maintenance will cost, I care about the cost of new engineering work, and I care about how predictable engineering estimates are. A well commented code base will help reap benefits in all those areas.

            I do agree with a lot of what you’re saying (although some of the things you point out are more coding problems than comment problems), but feel you’re way undervaluing comments.

            Can you send me a link to the accum_entry() source? I’m curious to see what it is that I’ve been missing out all these years.

          2. tribal knowledge? you assumed that was tribal knowledge? it’s a function name. it’s context-dependent knowledge. you’re looking at code that’s accumulating entries, is it reading them from a file, from the network, inventing them from scratch? you’d know if you were reading the code. and it has a book-keeping function to accumulate them. it’s obvious when you read it, and that comment doesn’t make it more obvious.

            “Now instead of working the assigned task, people are busy reading code trying to figure out what the boiler plate is doing. You save 5 lines, but now development costs more.”

            this is exactly backwards. they do indeed go through that task, but they can figure it out from context because it’s a well-factored, well-named function, and if they get curious about it, it’s short and they can tell how it works, or alternatively it’s complicated and there’s a comment describing its complications. but there’s no scenario where a comment that doesn’t tell them anything you couldn’t already tell by the name of the function gives them any help. they still have to do the work of reading, and if the comment is really that vapid, then they still have to read *the code* as well as the comment, which means now they have *extra reading*. and there are indeed scenarios where the function itself does something quite surprising that they need to know about, but which isn’t documented in these boilerplate style comments.

            good comments — *explanatory* comments — save time getting new developers up to speed. comments that repeat what the code already says do not.

          3. Whether it’s contextual knowledge or not, you made it tribal knowledge by deciding that everybody must know it already (which everybody doesn’t) and that it doesn’t need to be documented.

            “because it’s a well-factored, well-named function”
            But it’s not, your function name is ambiguous, and the parameter name is very ambiguous. It wouldn’t take much to improve it and make the comment obsolete. But until the code is improved, that comment you want to delete is adding more value than it’s detracting.

            “but there’s no scenario where a comment that doesn’t tell them anything you couldn’t already tell by the name of the function gives them any help.”
            Triple negative! I can see why you shy away from comments… ;)
            I already pointed out why that comment (poorly) gives clues that you don’t get from the function name/param name.

            Again, we are all different, we have different backgrounds and different experiences, and if you expect other people to work on code you wrote, you’ve got take that into account. From your discussion and examples you provided, I feel you’re a bit mis-calibrated on what good code is, your well-factored, well-named code looks very mediocre to me…

            So no link to this code that everybody should recognize?

          4. i made it up, that’s not a reference to some common code everyone knows. though you’ve seen code just the same, sometimes it’s named add_ent() or new_ESD(), add_entry_to_table() if you aren’t into the whole brevity thing. if you’re in the domain, it makes perfect sense what it does, and if it doesn’t then you need an *explanatory* comment.

            but here’s the most important thing. if you are somehow unaware what it does, if you have questions like: what is an entry? is this going in a list or hash table or what? is this on input from the file or is this for storing the result of intermediate processing? what is the memory management lifetime (does it copy its argument)? does it side-effect into the argument? what happens for duplicate entries? maybe “accum” or “entry” isn’t clear to you because english isn’t native. you might have a million questions. and this boilerplate won’t answer them. to refresh your memory:

            /*
            * accum_entry()
            * input: an entry to accumulate
            * return value:
            */
            void accum_entry(struct entry_rec *e)

            that comment literally dosen’t do anything but re-state the function signature in a more verbose and strictly redundant format. you see it in your own assessment, you think that the comment text “input: an entry to accumulate” means that e is an input value and not a return value. you believe the comment told you something about how e is used, namely, that *e is not side-effected into! the comment merely re-states the function signature to satisfy a corporate mandate for boilerplate comments but you erroneously believe it told you something about how the function works. if accum_entry() is a very simple function, you would know more by reading its code, and if it’s a complicated one then golly gee don’t you wish it had a quality comment instead.

            i am, to repeat myself to the point of tears, enthusiastically in favor of comments that answer questions people actually have. the bad comments are the ones that don’t do anything but repeat the computer code in human language.

          5. “add_entry_to_table()”
            That’s a big improvement, if you renamed the function to something a long those lines (with better param naming) and deleted the comment, I won’t care (it’s a net value gain).

            “because english isn’t native”
            Another great example of how we are all different and you can’t just assume everybody is going to know the same stuff as you.

            I agree the comment you gave as an example is a poor comment, but I still see some (a small amount of) value in it in the context provided. It does communicate more than just repeating the function signature.

            “the bad comments are the ones that don’t do anything but repeat the computer code in human language”

            “bad comments” are comments that mislead you or are just out right incorrect. Such as “// thread safe!” when something very not thread safe.

            I do agree with you for examples like:
            i++; // Increment ‘i’ by 1.
            But that’s already giving me the this-is-not-good-code vibe…
            Or if it’s something like:
            /* Implement accum_entry() */

    3. When I learnt to program in Prolog, it was usually necessary to put at least three comment lines for every line of code, as a minimum, or you didn’t have a cat in hell’s chance of knowing what the program did by inspecting it later, even if it was something you yourself wrote.

        1. Greg, what you’re failing to grant is that the code expresses _How_ the task is effected, but intelligent useful comments express _What_ is being achieved. There is a big difference, especially w.r.t. maintainability. That difference is something I always made my software team members aware of, if it was not already second nature. The classically dim “i++ // Increment i” is a “How” comment, redundant and useless. An intelligent programmer understands the value of meaningful variable names and comments.

          1. Actually, Greg is failing to understand some things:
            – first, he fails to see the difference between *documenting* and *commenting* the code. In his example with eleven lines of comment he fails to see that this is not a comment, this is inline documentation, and if properly done, can be translated in some human readable documentation
            – second, he fails to realize that comments are not about *what* or *how*, they are about *why*. What or how should be self-evident from the code, but reasons are not. In the real world things don’t always behave as we expect them to, and real world code often reflects that
            – third, in his trivial example with incrementing and index he is pulling a strawman to justify his attitude toward comments, there is no need for further comments (pun intended)

          2. man what a frustrating exchange. i agree ‘why’ comments are great. ‘what’ comments are sometimes good. ‘how’ comments are awful. i’ve said as much, so to hear it echoed back to me as if i didn’t get it is kind of *shrug*?

            you *have* to be able to read the language or you will need ‘how’ comments, and you will ultimately be left on a canoe without a paddle.

            and Martin, you missed my point entirely. i’m enthtusiastically in favor of documentation. they gave these boilerplate comments *INSTEAD OF* documentation. in the example i chose from raspberry pi CEC library, the foremost question of “what is passive mode?” is only answered in one place, in the 3-line in-line // comment in the middle of an enum, not formatted for document scraping. if you have the answer to that question, what is passive mode?, then the question of what does “vc_cec_set_passive(vcos_bool_t enabled)” do isn’t interesting. it’s *obvious* what it does. i don’t object to tediously documenting its inputs / outputs / error behavior, but since it’s obvious and the error handling behavior is identical to every other function in the library, it really truly is redundant.

            but you don’t know — i *still* don’t know — what passive mode *is*. so vc_cec_set_passive(bool enabled) is still opaque to me, even though they gave me all these redundant lines of boilerplate comment. i can tell you some characteristics of passive mode, but they’re all things i’ve learned from trial and error instead of documentaiton, and they make me feel like passive mode is a hack that never got cleaned up or debugged before release. and, like i said, the libcec guys came to the same problem, so it’s not just me being obtuse. at worst, it’s both of us being obtuse.

            and even knowing what passive mode is, i sure would love to know what implicit state changes happen within the firmware when passive mode is entered / exited, and, again, this question isn’t answered by the boilerplate comments. the comments take up a great deal of screen real estate and developer effort and don’t provide any value at all.

            and kind of a nitpick but they gave the boilerplate comments in two different places with slightly different content between them. so now they’ve got the possibility of going out of sync with eachother, and they also pose a real conundrum if someone does want to scrape them to make an API doc. it’s a boilerplate requirement that wasn’t well-thought-out beforehand, in addition to being only-phoned-in by the guy who actually had to abide by the requirement.

  7. > I don’t know of any machines with a native comment instruction.

    What’s this? You can comment in any machine language if it strikes your fancy. Simply jump unconditionally over the non-executable text.

      1. When you disassemble a program, the text sent to the screen often acts as markers. A text message comes up at a key point, find that message, then find how and where it’s displayed, and there’s the code that follows.

        You generally have to find those messages anyway, since the disassembler may treat it as weird code, but as text it makes sense.

        I haven’t done it in a long time, but I imagine disassembling is easier now. Redirect the output to a text file, and use a text editor to find useful points, return from subroutines and text messages.

        When I did it, it meant disassembing to the printer, and then spending lots of time scanning the results, marking key points, and likely doing it again as yiu find “code” that is actually data.

      1. A Turing machine is any machine that can emulate all the functions inside another Turing machine. It isn’t really an architecture, but rather a concept of what tasks a computer system can handle.

        A Harvard architecture can contain a function to jump unconditionally in the code to any arbitrary point. But it isn’t a strict requirement to be a Harvard architecture, but having jump instructions makes reaching Turing completeness easier in practice.

        Similar story for a von Neumann architecture, but they too don’t strictly need a fancy jump instruction, but it tends to help when it comes to being Turing complete in practice.

        But with a simple jump instruction, practically any architecture can have commented machine code. But commenting machine code is of dubious advantage in practice regardless. Better to spend the RAM on more useful stuff, like applications and datasets.

  8. We should remember that the first “computers” were people – often rooms full of them in wartime, working on calculating solutions to complex problems in physics/ballistics etc.

    Feynman recounted using colored cards to track the iterations and corrections as the problem progressed, so I would be that the first “program comments” were added to these as the solutions progressed.

  9. The first language I wrote a program in was SOAP for the IBM 650 in 1957 or 1958. I got to accompany my dad once in a while when he was called to fix the beast. The bored engineers explained lots of stuff to a curious kid. Over time they taught me to write a (trivial) program in SOAP while they waited for my dad to finish. I was addicted. SOAP had comments.

    See . To quote the article “Each source card can contain up to ten characters of comments in columns 63–72. For longer comments, up to thirty characters may be entered on a Comments Card (Type 1, ‘1’ in column 41) in columns 43–72 “

    1. yeah, and some even have a small data field in it. for example, “branch-on-condition cond,addr” if you fill in cond with 0 then the branch is never taken, and then you can hide whatever data you want in the address field.

  10. What do you mean by “saving the comments along with the code”? The “code”, as used there, implies source code, not machine code. No assembler or compiler saves comments in the machine code. Saving comments in the source code was possible as soon as computers had enough offline storage to do so. As mentioned earlier, this might have been about the time that punched cards were used for computer storage. Since there was extra space on the card, it was obvious that comments could be put there, and the computer had no problem transcribing them to program printouts.

    1. Wikipedia says Fortran was introduced the year before Lisp. Wikipedia also says Fortran has comments.
      No idea though if the early versions also allowed for comments. According to some internet sources you can comment in Fortran with a variety of signs. Namely “c, C, *, d, D, or !” Which makes me think that it is not directly part of the language but rather an add-on introduced by the implemented interpreters / translators. Therefore might have been bolted onto the language later on.

  11. Comments in code are bad in the long term. As code is changed over the years, bugs are fixed, new edge cases are added, low-level libraries get replaced, new compilers, etc. The comments are not kept up to date and at some point they don’t reflect the code any more. All the other changes in the code can be tested but there are no tests to assure the continued accuracy of the comments. If you can’t test it you must assume it is broken.

  12. Maybe the first comments were hand-written notes on punch cards used for programming weaving machines or book music organs. These machines were basically mechanical computers. Although you could argue they are too simplistic and too specific to be called general computers.
    Or maybe notes next to mathematical formula’s that were algorithms predating computers. Those algorithms were written for humans to execute, not computers, but it was still code.
    Some computers were programmed using wiring. Maybe notes in wiring diagrams? Maybe this is too close to hardware to be called software.
    The first code written by Alan Turing probably had notes.

  13. I think it matters if you are talking about “storing comments on the disk/drum/etc.” with the code, or if it is part of the running system in core. If the latter, then my guess would be Lisp. Back when I used InterLisp, comments could look like functions, and further when the language was interpreted, it was stored as part of the function definition (so could be retrieved while debugging the function). Lisp is probably the earliest interpreted high-level language (only Fortran is older and it was always compiled); compilation was added later (interestingly enough, with somewhat different semantics from the interpreted code, so your code could act differently if was compiled). All that’s been cleaned up since then, and I don’t think modern lisps store the comments anymore as part of the function definition in-memory.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.