1. 4

    On the Excel team we had a rule that whoever broke the build, as their “punishment”, was responsible for babysitting the builds until someone else broke it.

    I’m torn between curiosity of wanting to know what “babysitting the builds” could possibly mean and the fear of actually finding out.

    1. 3

      You kids and your CI tools …

      The daily build, particularly on a large project (and I’m sure Excel was a prime example of a large project), wasn’t entirely automated. I mean sure, there are makefiles and scripts and everything, but nothing like the kind of automation that we take for granted nowadays. So someone had to watch over the build process, and take note if and when it failed. They would then have to figure out if it failed because some transient issue, like a network router was temporarily insane, or if someone had actually checked in a bug. If the latter looked more likely, that person had to track down the actual offender.

      The above-quoted rule provides some necessary motivation for the current babysitter to actually take this job seriously and follow through on what can often be a tedious process.

    1. 1
      1. Surprising math:

      int x = 0xfffe+0x0001;

      looks like 2 hex constants, but in fact it is not.

      But what is it? For me that’s a syntax error and gcc agrees:

      error: invalid suffix "+0x0001" on integer constant
          2 | int x = 0xfffe+0x0001;
            |         ^~~~~~~~~~~~~
      

      Am I missing something?

      1. 2

        What is it? It’s a syntax error, as you determined.

        If you’re asking why it’s a syntax error, I believe it’s because the letter e directly followed by a plus or minus sign is used to provide the exponent of a floating-point value. It’s not legal to use this syntax on a hexadecimal constant (that’s done with the 0xfffp+1 syntax), but I’m assuming that the C standard doesn’t allow this syntax to avoid confusion.

        Adding a space before the plus sign makes the syntax error go away.

        1. 2

          If you’re asking why it’s a syntax error, I believe it’s because the letter e directly followed by a plus or minus sign is used to provide the exponent of a floating-point value. It’s not legal to use this syntax on a hexadecimal constant (that’s done with the 0xfffp+1 syntax), but I’m assuming that the C standard doesn’t allow this syntax to avoid confusion.

          That’s also my understanding of the code presented.

          Adding a space before the plus sign makes the syntax error go away.

          Yes. And then it’s also “2 hex constants” and nothing fishy is going on. I still don’t see the point of the author :D

        2. 1

          I tried this with gcc -std=c89 and it still won’t parse. I tried with DeSmet C from 1985 and it doesn’t complain, but it also doesn’t do anything surprising.

          C:\WOZ>type abuse.c
          #include <stdio.h>
          
          main()
          {
            int x = 0xfffe+0x0001;
            printf ("%x\n", x);
            return 0;
          }
          C:\WOZ>c88 abuse.c -Ic:\desmetc\
          C88 Compiler    V2.51    (c) Mark DeSmet, 1982,83,84,85
          end of C88        001F code   0004 data       1% utilization
          C:\WOZ>bind abuse.o
          Binder for C88 and ASM88     V1.92    (c) Mark DeSmet, 1982,83,84,85
          end of BIND        9% utilization
          C:\WOZ>abuse
          FFFF
          

          Since DOS uses 16-bit integers if you print that with %d you’ll get -1, but again, this is expected.

        1. 4

          This is a cool technique that I was not aware of.

          Like many people, I eventually settled on doing this via the .incbin assembler directive. The following macro shows the technique, and is pretty portable:

          #define incbin(filename, symbol, endsymbol)                 \
          extern unsigned char const symbol[] __asm__(#symbol);       \
          extern unsigned char const endsymbol[] __asm__(#endsymbol); \
          __asm__(".globl " #symbol "\n"                              \
                  ".globl " #endsymbol "\n"                           \
                  #symbol ":\n"                                       \
                  ".incbin " #filename "\n"                           \
                  #endsymbol ":\n")
          

          (Unfortunately, using extern seems to be necessary; using static works on Linux, but fails on the Mac, for example.)

          BTW, the __asm__(#symbol) tags are there to counteract platforms that prepend underscores to linkable symbols. If you’d rather have the underscores, you could instead embed prefixed underscores to all the symbols in the assembler – and then use __asm__("_" #symbol) to counteract platforms that don’t prepend underscores.

          1. 3

            An even more portable version of this technique: https://github.com/graphitemaster/incbin

          1. 5

            I have always enjoyed the retroactive mnemonic naming of the registers EAX-EDX (accumulator, base, count, data). It almost makes you believe that the whole thing was actually planned, and not a complete mess of gradual evolution.

            An interesting side note is the Z80, which was basically an evolution of the 8008. It had the exact same basic register names of A, B, C, D, E, H, and L. But they extended the 8008’s idea of pairing H and L to create addresses, much as the 8086 did, and combined six of the 8-bit registers to make three 16-bit registers – so they had the registers BC, DE, and HL. As with the 8086, these were not truly generic, but had different specializations. HL and DE were used and source and destination registers in copy operations, and BC was used as an implicit loop counter. So BC and DE were naturally given the retroactive mnemonics of Byte Counter register and DEstination register, respectively. Almost as if they had planned it that way all along.

            1. 3

              This sort of thing is a good reminder that tech-savvy people are just as prone to conservatism as anybody else. We are all in favor of disrupting existing systems, as long as they aren’t the ones we have grown accustomed to.

              1. 2

                As mostly a hobby I am rewriting a MS-DOS game in C with the eventual goal of actually running it on MS-DOS (probably via DosBox). Currently it uses SDL2 but I will write other video output “drivers” (e.g. allegro) to target older operating systems. Ideally I’d like to use C++ but I think I’m not sure how to target MS-DOS with C++11 or 14. The last versions of Borland and Watcom don’t even officially support C++98.

                1. 3

                  There are no C++ compilers that target 16-bit 8086, short of going back to Borland et al. as you mentioned. However, MS-DOS will run programs compiled with 32-bit i386 instructions, and gcc does support that target. Use the gcc flags -m32 -march=i386. Unfortunately you probably wouldn’t have access to a working libc, so you’d need to reimplement standard library calls yourself. Then the remaining issue is finding a linker script that produces MS-DOS .EXE files. (Or, if your program can fit in 64k, you could just dump it to a .COM file and run that.)

                  1. 1

                    I’d say djgpp, but I think that’s on an old GCC still.

                    1. 2

                      It’s not. 9.2.0 came out last year: https://groups.google.com/forum/#!topic/comp.os.msdos.djgpp/RO-Mx0PhYcc IIRC, you can’t build real mode executables with it, only protected-mode.

                  1. 5

                    “Read the documentation” is something I always hear, but since I started working professionally as a programmer, the projects I encountered had either very sparse and outdated documentation or none at all.

                    I recently raised this point and offered to improve the documentation, and got an “Oh that’s a good idea but once you know how it works other people can just ask you. We really would like to focus on features instead of documentation.”.

                    This and “If you need comments to understand code, you’re a bad programmer.” pretty much imply that it’s preferable to have a repo that exists of just code, without any prose.

                    1. 5

                      Author here.

                      I recently raised this point and offered to improve the documentation, and got an “Oh that’s a good idea but once you know how it works other people can just ask you. We really would like to focus on features instead of documentation.”

                      That’s frustrating. It feels similar to “we don’t really need automated testing, we can just do it manually”. Of course there are more and less useful tests. Of course there is more and less useful documentation. But good docs written once free up your time to work on features and enable other devs to spin up more easily and hence write more features.

                      Plus, I can’t count the number of times I’ve documented something, gone away for a while, and come back to it. I can re-read my docs and, again, do the task or make the change far quicker than I could have without the docs. It doesn’t just help other people, it helps me!

                      Another case of go slow to go fast.

                      1. 2

                        That’s a great point. I’m often documenting things for myself due to lack of official documentation, but I rarely contribute it back, which doesn’t make a lot of sense. I think it’s a mixture of laziness and lack of self belief (thinking it won’t be appreciated or wanted), but I know how irrational that is. If I’m looking at documentation and feeling frustrated, and I know I can improve it, then I’m certainly not the only one. Now I’m feeling motivated to get more involved!

                        1. 1

                          That’s great!

                          To be fair, sometimes doc feedback isn’t welcome (or needs to be formatted a certain way, a license agreement signed or has some other condition that requires a bit more work). But in my experience that is more often the case for larger, corporate docs. Internal doc maintainers are, in my experience, much more forgiving.

                      2. 1

                        Some of this depends on the size of the company. With a small enough engineering team, the idea of “just asking” can make sense, assuming there’s deadline pressure in the equation. (If there isn’t, then ffs just write the docs.) But as soon as you go beyond, say, 7 people, going without docs is almost always a bad idea.

                        The other reason companies are loathe to spend time documenting things is because things are often in flux. Documentation often slowly degrades, and it’s often unclear (except in hindsight) when it reaches that point where it’s become so wrong that it does more harm than good.

                        The other response, that documentation is for mediocre programmers, is virulently toxic. Best to either confront it head on, or schedule time to update your resume.

                        1. 2

                          Documentation often slowly degrades, and it’s often unclear (except in hindsight) when it reaches that point where it’s become so wrong that it does more harm than good.

                          Agreed it’s a constant struggle. It’s a bit like automated tests. They too require care and feeding above and beyond the code. In both cases the additional effort costs in the near term but allows additional speed on the long term (in the case of documentation, by allowing for scalable knowledge transfer to team members new to the system).

                          I also think how much the system is changing definitely should impact how much documentation aus written and how detailed it is. But even a note in the readme saying “this system is in flux” counts (and helps).

                      1. 3

                        I think this guy is taking this whole thing way too seriously. Gullible folks are going to be gullible…

                        1. 6

                          That’s a bit too glib, I would argue. There will always be gullible people, yes. There will always be disease, but we can still meaningfully improve people’s lives by fighting against it and educating people to avoid high-risk behavior.

                          Plus, even if you don’t care about other people, an uneducated population is bad for everyone else.

                        1. 3

                          I’m in the middle of listening to the Socratic dialog on Audible. I’ll be honest, from where I stand, Socrate documenting an API would be him claiming that he does not know what a good API is, then asking me to try to explain to him what make a good API, then after I said something, he would hijack the conversation for 20 minutes where he would rave about the good and why since a physician is good by the virtue of curing the disease, the API is good by virtue of curing the database of its inconsistencies (or whatever), then use that long harangue to display to me that I don’t know what a good API is, then I would ask him a bit frustrated “well, what make an API good”, to which he would answer that he does not know because he does not know what the “good” is and that he need me to teach him. Go back to beginning and start over, until I get frustrated and start thinking that this guys would sure deserve to be put to death for being so damn annoying.

                          Of course he would barely mention the API itself, but then, since we don’t know what the good is, we can’t know what a good API is, and because of this, we cannot know if that particular API is of any good. “And yet, you seems to know what a great API is, but you refuse to tell me!” would probably have been uttered at some point in the dialog.

                          Yeah, the Socratic dialog are great to listen to. 😆

                          1. 2

                            Yes, the term “Socratic dialog” has come a long way from what Socrates himself actually engaged in. But then, it has been a couple thousand years, so maybe that’s not surprising.

                          1. 5

                            This is a very interesting idea. Unfortunately, the essay itself is Euclidean instead of Socratic.

                            It would be very helpful to have some short exceprts that demonstrate the Socratic approach, and show how it helps the user understand some internal detail of a system. And maybe some examples of the sort of easy mistakes that you should look out for when writing in a Socratic style. And, of course, examples of Socratic documentation, even mediocre examples, from real-world APIs. Oh, and obviously a FAQ would be nice.

                            Oh well, at least the absence of these things helps make it clear why they are good things to have!

                            1. 12

                              I don’t think he was framed. I think the article explains that McIlroy is doing a literature review in the spirit of Knuth’s literate programming, and the shell script was written in the context of reviewing Knuth’s literate program as a program and as literature. The fact that two people who were discussing an article neither of them had read came to a conclusion that isn’t supported by the article is unsurprising (and common in discussing “the classics” of programming literature).

                              1. 17

                                “Knuth’s 1986 Literate Programming Article Has Been Taken Out of Context” just wasn’t gonna get the clicks.

                                1. 15

                                  This was a newsletter post. It was sent to people who already signed up to receive my emails. I decided to have a bit of fun with the title, and wasn’t expecting it to go so viral outside of my regular readers.

                                  1. 9

                                    No snark intended beyond good fun; it was a good article, and yours is the better title. I’m tempted to subscribe.

                                    1. 9

                                      All good! As we all know, tone carries 100% perfectly on the internet

                                  2. 7

                                    “A programmer tried Literate Programming - you won’t believe what happened next!”

                                    1. 4

                                      Wait until a lobster reads the rest of the “premature optimisation” paper.

                                      1. 3

                                        What‽ I would have clicked on that in a beartbeat!

                                      2. 14

                                        If one reads the original article (which is quite long, both on the LP part and the response, it’s clear no framing was being done. I think the “framing” is the decades-long game of telephone afterwards which boiled down to “Donald Knuth’s 10 page LP opus was replaced by a very small shell script”.

                                        1. 3

                                          (and common in discussing “the classics” of programming literature).

                                          My favourite example of this is the diatribes you see sometimes around ‘single exit from a procedure’ and gotos in general. ‘Procedures should be single entry, single exit’ is about avoiding jumping into and out of procedures in unexpected places. It’s not about a single return statement at the end of a function! And ‘goto’ is considered harmful when it’s used to jump into the middle of random functions and in place of structured programming facilities like if/else statements and loops, not when it’s used to implement a state machine!

                                          1. 2

                                            And ‘goto’ is considered harmful

                                            This is exactly what I’ve been thinking about, parts one and two (which I can’t submit to lobsters as I’m a content marketer)

                                            1. 1

                                              Programmers are no less immune to arguing from authority or cargo-culting than other people.

                                              1. 3

                                                I think it’s more common in programming than in other fields, that, in comparison to programming, have long-established rigorously-derived bodies of knowledge.

                                                1. 1

                                                  You’d be surprised! From my discussions with people in other industries, cargo culting is pretty universal. Remember, it took decades to get doctors to wash their hands!

                                          1. 13

                                            I found this to be a lovely 30-minute read on C’s motivation, history, design, and surprising success. I marked down over 50 highlights in Instapaper.

                                            If you haven’t written C in awhile, you should give it a try once more! Some tips: use a modern build of clang for great compiler error messages; use vim (or emacs/vscode) to be reminded C “just works” in editors; use a simple Makefile for build/test ergonomics.

                                            In writing loops and laying out data in contiguous arrays and structures, remind yourself that C is “just” functions, data atoms, pointers, arrays, structs, and control flow (plus the preprocessor!)

                                            Marvel at the timeless utility of printf, a five-decade-old debugging Swiss army knife. Remember that to use it, you need to #include <stdio.h>. As Ritchie laments here, C regrettably did not include support for namespaces and modules beyond a global namespace for functions and a crude textual include system.

                                            Refresh your memory on the common header files that are part of the standard and needed for doing common ops with strings, I/O, or dynamic heap allocation. You can get a nice refresher on those in your browser here:

                                            https://man.cs50.io/

                                            Overall, you’ll probably regain some appreciation for the essence of programming, which C represents not due to an intricate programming language design with an extensive library, but instead due to a minimalist language design not too far from assembly, in which you simply must build your own library, or rely directly on OS system calls and facilities, to do anything useful. There is something to be said for languages so small they can truly fit in your head, especially when they are not just small, but also fast, powerful, stable, ubiquitous, and, perhaps, as timeless as anything in computing can be.

                                            1. 5

                                              I don’t think that a lack of namespaces is really something to lament. _ is prettier than ::. For all the handwringing you see about them, I’ve literally never seen a symbol clash in C ever.

                                              1. 5

                                                I love C and it continues to be my first language of choice for many tasks, but namespaces are the first thing I’d add to the language if I could. Once programs get beyond a certain size, you really need a setting between “visible to one file” and “visible EVERYWHERE”. (You can get some of the same effect by breaking your code up into libraries, but even then the visibility controls are either external to the language or non-portable compiler extensions!)

                                                And for the record, I’d prefer an overload of the dot operator for namespaces. Or maybe a single-colon operator – some languages had that before the double-colon became ubiquitous.

                                                1. 2

                                                  I tend to agree that this isn’t a huge issue in practice, especially since so very many large and well-organized C programs have been written (e.g. CPython, redis, nginx, etc.), and the conventions different teams use aren’t too far apart from one another. As you noted, they generally just group related functions together into files and name them using a common function namespace prefix, like ns_. But, clashes are possible, and it has meant C is used much more as a starting point for bespoke and self-contained programs (again, CPython, redis, and nginx are great examples), rather than as a programming environment to wire together many different libraries, as is common in Python, or even Go.

                                                  As dmr describes it in the OP, this is just a “smaller infelicity”.

                                                  Many smaller infelicities exist in the language and its description besides those discussed above, of course. There are also general criticisms to be lodged that transcend detailed points. Chief among these is that the language and its generally-expected environment provide little help for writing very large systems. The naming structure provides only two main levels, ‘external’ (visible everywhere) and ‘internal’ (within a single procedure). An intermediate level of visibility (within a single file of data and procedures) is weakly tied to the language definition. Thus, there is little direct support for modularization, and project designers are forced to create their own conventions.

                                                  1. 2

                                                    I don’t really think that namespaces are the reason people don’t use C for gluing together lots of other C programs and libraries. I think people don’t do that in C because things like Python and Bash are a million times more suitable for it in a million different ways, only one of which is namespaces.

                                                    Large systems don’t need to all be linked together with one big ld call. Large systems should be made up of small systems interacting over standardised IPC mechanisms, each of which of course have their own independent namespaces.

                                                    There’s also the convention we see of lots of tiny files, which is probably not actually necessary today. It made more sense in there days of centralised version control and global file locking in very old version control systems where merging changes from multiple people was difficult or impossible and one person working on a file meant nobody else could. But today, most modules should probably be one file. Why not?

                                                    For example, OpenBSD drivers are usually a single .c file, for example, and they recommend that people porting drivers from other BSDs merge all the files for that driver into one. I actually find this easier to understand: it’s easier for me to navigate one file than a load of files.

                                                2. 4

                                                  If you haven’t written C in awhile, you should give it a try once more! Some tips: use a modern build of clang for great compiler error messages; use vim (or emacs/vscode) to be reminded C “just works” in editors; use a simple Makefile for build/test ergonomics.

                                                  I am going through the Writing An Interpreter In Go book but in C (which is totally new to me, coming from a JavaScript background) and it’s been the most fun I had in years. I’m actually starting to get quite fond of the language and the tooling around it (like gdb and valgrind).

                                                  1. 2

                                                    I recommend you take a look at http://craftinginterpreters.com as well, if you want something similar for C. The book is in two parts: the first part a very simple AST-walking interpreter written in Java, the second part a more complex interpreter that compiles the language to bytecode and has a VM, closures, GC, and other more complicated features, written in C. If you’ve already read Writing An Interpreter In Go you can probably skip the Java part and just go straight to the C part.

                                                    1. 3

                                                      Thanks, I will (after I’m done with this). I actually really liked it that the book is in Go but my implementation in C, as it made it a bit more exciting for me to think about how I would structure things in C and see what the tradeoffs are versus doing it in Go. Otherwise I’d be tempted to skip entire chapters and just re-use the author’s code, which obviously doesn’t help if my goal is to learn how it’s actually done.

                                                  2. 4

                                                    so small they can truly fit in your head

                                                    Very true. One thing I’ve noticed, going to C from Rust and especially C++, is how little time I spend now looking at language docs, fighting the language or compiler itself, or looking at code and wondering, “WTF does this syntax actually mean?”

                                                    There’s no perfect language though. I do pine sometimes for some of the fancier language features, particularly closures and things which allow you to directly concepts directly in code, like for(auto i : container_type) {...} or .map(|x| { ...}).

                                                    1. 1

                                                      One thing I’ve noticed, going to C from Rust and especially C++, is how little time I spend now looking at language docs, fighting the language or compiler itself, or looking at code and wondering, “WTF does this syntax actually mean?”

                                                      It’s also really nice being able to type:

                                                      man $SOME_FUNCTION
                                                      

                                                      to get the documentation for any function in the standard library (and many others not in the standard library). I do a lot of my development on the train (without access to the internet) and man pages are my best friend.


                                                      On the topic of “wtf does this syntax actually mean” I do think C has some pain points. East const vs west const is still a point of confusion for many, and C’s function pointer syntax will melt your brain if you stare at it too long.

                                                      At one point I wrote a C backend for a compiler I was working on and needed to really understand how declarations worked. I found that this article does a really good job explaining some of the syntax insanity.

                                                    2. 4

                                                      If anyone is looking to give modern C a try I would recommend reading How to C. It’s a short article that bridges the gap between C from K&R Second Edition and C in $CURRENT_YEAR. The article doesn’t cover the more nuanced details of “good” C programming, but I think that K&R + How to C is the best option for people who are learning the C language for the first time.

                                                      1. 2

                                                        Awesome recommendation! As someone who is picking up C for some programming fun & tasks again after a decade-long hiatus (focused on other higher-level languages), this is super useful for me. I have been re-reading K&R 2nd Ed and been looking for something akin to what you shared in “How to C”.

                                                        I also found these two StackOverflow answers helpful. One, on the various C standards:

                                                        https://stackoverflow.com/questions/17206568/what-is-the-difference-between-c-c99-ansi-c-and-gnu-c/17209532#17209532

                                                        The other, on a (modern) set of useful reference books:

                                                        https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list/562377#562377

                                                    1. 4

                                                      One of the easiest way to do this is probably by reading the file with mmap: backtracking is as simple as pointer arithmetic and memory is magically managed by the kernel. Forget reallocs in loops and off-by-ones. It won’t work with streams though.

                                                      1. 3

                                                        It also won’t work with special virtual files. Take /proc/cpuinfo on Linux for example. Depending on your tool, your users will expect it work on such things.

                                                        1. 5

                                                          This gives me a bad idea for faking making it “work” for pipes, along the lines of http://t-a-w.blogspot.com/2007/03/segfaulting-own-programs-for-fun-and.html

                                                          Carve out a huge area of address space with one big mmap() call, mprotect it all to PROT_NONE. When the main program tries to access it, catch the sigsegv, mprotect() it to read/write, read(2) one full page from the pipe to fill out the input block and then return from the sigsegv handler. Assuming read(2) is safe to call from a synchronous signal handler, which I’m not sure whether it is or not.

                                                          This is silly and really complicated, completely defeating the concept of making it “easy”, but you could hide it all behind one function call. ;) Plus it’ll crash when the address space runs out (after, like, several terabytes?) and I suppose there’s no sensible way to communicate the length of the file but… eh whatever. I never claimed this was a good idea. :)

                                                          1. 2

                                                            That’s super interesting! I’ll try to play with this silly idea this weekend.

                                                            1. 2

                                                              If you do, please share your results with lobste.rs! I know I would at least fine it interesting!

                                                              1. 2

                                                                So I tried to implement this and unfortunately it doesn’t work for most streams. That’s because there’s no way to use mprotect on something smaller than a page, and this is an issue just after calling read(), when you want to split the memory map in two part: An allowed part for already read characters, and a forbidden part for characters that will need to be read. These two parts must have different protections but unfortunately this is not possible if the boundary between the parts is not page-aligned. So it could work if you can read the stream in chunks of 4KB but not if it’s something written by a human on stdin.

                                                                1. 2

                                                                  Bummer. Thanks for following up!

                                                              2. 2

                                                                Imo there was no need to strike out the word silly ❤

                                                          2. 2

                                                            I imagine it would also fail with files that are larger than available memory (assuming the program actually touches every page).

                                                            Of course, it’s rather unlikely for a text file to exceed available memory nowadays, but I’ve seen some nightmare logfiles that were many GB in size.

                                                            1. 2

                                                              When you mmap() an ordinary file read only, you’re limited by address space but not by memory. The kernel is free to discard pages from the mapping that you haven’t touched in a while, cuz it can always reload them from the file later if it needs to.

                                                              You’re right that the 32 bit address space limit is inconvenient but you can still do this on finite amounts of RAM. ❤

                                                              1. 1

                                                                Yes it’s something to consider on 32 bit systems.

                                                            1. 11

                                                              The late adoption of getline() into the POSIX standard is probably responsible for its lack of widespread familiarity. Which is a terrible shame, because it’s a wheel that so many programs have had to reinvent.

                                                              1. 7

                                                                Usually people are surprised to find out that isn’t a GNU extension (any more), because they are used to POSIX being limiting and cumbersome to work with.

                                                                1. 2

                                                                  But it has also somehow failed to make it into the C standard. Which is kind of sad.

                                                                1. 8

                                                                  Comments that have typos or are otherwise sloppy seem more likely to have bugs near them, either nearby in the code or in the same commits.

                                                                  Code pushed by people just before going on vacation should get extra scrutiny.

                                                                  If you’re converting/compressing and transferring something, multiple layers of checksums can help figure out which layer is screwing it up. It’s easier to add them and then disable them once everything is working properly.

                                                                  Sometimes starting from scratch and rewriting a prototype of something from memory is a good way to rethink the core design.

                                                                  1. 2

                                                                    Comments that have typos or are otherwise sloppy seem more likely to have bugs near them, either nearby in the code or in the same commits.

                                                                    I agree with this in principle, except that there’s too much noise in this signal from people who are just bad at spelling and/or grammar. The real signal is when someone is being uncharacteriscally sloppy, which requires you to be familiar with that person’s language habits.

                                                                    Code pushed by people just before going on vacation should get extra scrutiny.

                                                                    Oh good grief yes, a thousand times. I’d go even further, and say that people should not be permitted to push code right before a vacation, at all.

                                                                    1. 1

                                                                      Yes, when somebody whose general writing voice you know is being uncharacteristically sloppy. That’s a great way of putting it.

                                                                      I’m thinking of someone at a previous job who usually wrote well, but typos in comments often correlated with bugs – using the wrong constant for some calibration value, for example – and I realized it could have been a sign he was mentally exhausted but hadn’t realized it yet.

                                                                    2. 1

                                                                      Comments that have typos or are otherwise sloppy seem more likely to have bugs near them, either nearby in the code or in the same commits.

                                                                      This is generally true, but not always. I have a colleague that everybody recognizes as a “superproductive programmer” who is unable to write a sentence without a few orthography or grammar errors. Even worse, he uses inconsistent formatting and spacing in his code, and he does not care. Yet, I have never seen anybody else able to write a continuous stream of useful and working code without bugs and very well-organized overall. Some people seem to just think at a higher level (and not at a lower level at the same time). This is not a matter of typing speed, he also types quite slowly.