1. 18

  2. 9

    The problem with memes like this is that they require context to understand and the context is missing. This one gets reduced in many peoples’ minds to “performance doesn’t matter,” resulting in a lot of very slow code. What it really means is much more nuanced and boils down to several considerations: don’t compromise your ability to think about the solution by prematurely worrying about speed, don’t waste time micro-optimizing before you get the design right, use profiling to prioritize your optimization work, and optimize at the algorithm choice and design level before worrying about code level performance or micro-optimizations.

    Another one I dislike is “don’t roll your own encryption.” I now see it used all over the place in context where it doesn’t make sense, and it carries none of the important understanding of why encryption is harder than other kinds of code or how you should go about approaching crypto if you do find yourself needing to develop some.

    1. 3

      Much like ‘don’t reinvent the wheel’ and cries of ‘NIH’ if you dare to write something yourself.

    2. 9

      Nowadays it is common knowledge that you should build things to work and only then optimize them to work fast. For me it sounds like: “let’s build a house of straw and beeswax and call the fire brigade when it catches fire”. It’s absurd for every other engineering discipline apart from software engineering. We are here to anticipate and prevent the problems, and not to spawn them ignorantly because of 45 years of self-deception.

      Software engineering is different from structural engineering. Software is easy to change, even on a running system. I can’t change a bridge after it’s built.

      When you build a “software bridge”, a lot of the times you don’t know if it will only be used by the occasional cyclist, or if there will be non-stop trucks driving across it. In the original version of my analytics product the DB persistence code was extremely naïve and fairly slow. But … it was very quick to write, easy to verify that it was correct, and “fast enough” for the current use case. At the time it wasn’t clear if there would be more users than just me; now that there are I’ve rewritten it to be much more efficient. It wasn’t clear from the outset if that was actually going to be needed, so it was better to spend my time on other things.

      I’ve built entire billing systems for applications that never got a single customer. In hindsight, it would have been much better to have spent the time on building a better application, and write the billing part only when it became clear it was going to be needed (i.e. we got some customers).

      I think this posts misses some of the economical realities of developing software; especially for younger companies (“startups” if you want to be hip about it) there there is only a limited amount of time and money to make it sustainable, and accruing some amount of technical debt just to push out various features out of the door is perfectly reasonable. Of course, in the long run you spend more time, but that’s how debt works: if I borrow €100k from the bank I end up paying €110k or more, but with that money I have the opportunity to built something of value (hopefully) that I wouldn’t have otherwise.

      A lot of the examples in this article are either accidental bugs (they happen), or things that at the time of writing, probably didn’t matter all that much since there were only cyclists and not 10-ton trucks. It’s easy to go back on that code years later and go “omg were these people idiots?!” but that’s discarding the context in which it was written.

      Products like Microsoft Word have a 36 year history with a lot of backwards compatibility. Just like when I’m in a plane taking off, sometimes I’m amazed any of this works at all.

      1. 4

        Software engineering is different from structural engineering. Software is easy to change, even on a running system. I can’t change a bridge after it’s built.

        A bit of a pet peeve of mine: this is untrue. Bridges are retrofitted, reinforced, and widened all the time. I’ve even talked with engineers who were tasked with physically moving an entire bridge after it was already in place. And civil structures that aren’t bridges (like houses) are changed regularly while people are still using them.

        1. 2

          Yeah, you’re right; I should have said that “you can’t easily change a bridge”, or something like that.

          (and of course, not all software is always easy to change either, but if your architecture is vaguely sound, then usually individual parts tend to be quite easy to replace/optimize at low cost, compared to significantly reinforcing a bridge anyway).

      2. 4

        I think mentions of this quote end up being Rorschach tests, to steal Dan Luu’s term. They’re rarely specific enough to generate a productive discussion. Instead, they express a certain sentiment, and people react to that, rather than to anything concrete. I’ve seen people mention the quote in circumstances where optimization really would be premature, and I’ve seen people mention it to justify not addressing easily anticipated performance problems. I have thoughts about which case are which, but no real thoughts about the quote.

        Two things I do like:

        Carlos Buena’s Mature Optimization Handbook

        Dan Luu’s Reasoning About Performance, which is a nice example of putting up-front thought into designing for performance.

        1. 3

          None of the examples in this article appear to be examples of premature optimization. All of them appear to be examples of inappropriate design, or picking the wrong tool (approach) for the job.

          Premature optimization means assuming that a reasonable, idiomatic, default way of solving some problem is going to be too slow, and using instead a complex, obscure, nonidiomatic, or otherwise difficult-to-maintain version of that solution without having justified its costs.

          (I find that developers who tend toward premature optimization have a high tolerance for [local] complexity, and don’t tend to appreciate, or leverage, consistent high-order system design. This seems to be a personality thing more than anything else. I’m not sure they’re better or worse developers for it, just something I’ve noticed.)

          1. 3

            When I think of this I tend to think about the risk of adding complexity to improve performance locally that then makes it harder to optimize the system globally. What ultimately matters is the performance of your whole system. If you add complexity before you’ve built and measured the performance of the system it may be harder to make larger scale changes that make a bigger difference.