1. 10

  2. [Comment removed by author]

    1. 7

      My boss at my previous company was dogmatic to the point of perversity. During code reviews, strict adherence to coding style guidelines (PEP-8+100 for Python, his own for C that included shudder Hungarian notation) was more important than the actual meaning of the code.

      I get that consistent style is important, I do, but we spent more time in code reviews discussing how to format our commit messages than we did talking about the algorithms being developed.

      Sometimes in C I really need try/finally, and the easiest, clearest, most maintainable way to do that in C is with goto statements to a cleanup label at the end of the function. I cringe when I want to do that because I know the battles that will come, due to another “considered harmful” article.

      “If you want to go somewhere, goto is the best way to get there.” – Ken Thompson

      1. 4

        This is why I like tools like gofmt and rustfmt. They make a lot of these decisions for you, automatically, so that there’s nothing to argue about.

    2. 7

      Without code examples, this is just “I prefer abstract principle A over abstract principle B”. Thus not a useful contribution to the literature, unfortunately, though I think the author would be great to talk to about this in person.

      1. 6

        I take exception with this part of the article:

        For instance, in a web application, a CRUD operation like “create user” can be “one thing”. Typically, at the very least, creating a user entails creating a record in the database (and handling any concomitant errors). Additionally, creating a user might also require sending them a welcome email. Furthermore, one might also want to trigger a custom event to a message broker like Kafka to feed this event into various other systems.

        Thus, a “single level of abstraction” isn’t just a single level. What I’ve seen happen is that programmers who’ve completely bought in to the idea that a function should do “one thing” tend to find it hard to resist the urge to apply the same principle recursively to every function or method they write.

        createuser should not contain a database call unless that it literally the only thing that needs to be done to add a user. Given the example above, createuser should, IMHO, look like this:

        createuser(const char *username, const char *email)
            int uid = insertuserintodatabase(username, email);
            if (uid < 0)
                return handledbfailure(username, email), -1;
            if (sendwelcomeemail(username, email) != OK)
                return handleemailfailure(username, email), -1;
            if (sendbrokercreateusermessage(uid) != OK)
                return handlebrokerfailure(uid), -1;
            return OK;

        In other words, there should be as many layers of abstraction as are reasonable. “One thing” should be one meaningful thing to a human, not the computer.

        1. [Comment removed by author]

          1. 4

            I mean, if you’re in Python, yeah. If you’re using a functional language this is seldom the case.

            1. 2

              Yup. My scala functions are rarely more than a few lines.

            2. 1

              “Don’t say you’re doing top-down design, if you’re actually doing bottom-up.”