
Like many left-brain people, I am constantly frustrated by imperfection. But I’ve decided that perfectionism is totally irrational.
Many great technologies are designed with tolerance to imperfection, including the internet protocol, HTML, CSS, and JPEG images, which together form the underlying framework of modern web browsing.
To visit a website, your browser sends a request to the specific computer that hosts the website, using what’s known as the internet protocol. This request is a tiny, neatly-formatted packet of data, sent into the vast ocean of packets that make up the internet like a message in a bottle; it might make it to the intended host, and it might not. Similarly, the data sent back to you might make it, and it might not. There are no guarantees. Sometimes data packets are annihilated on purpose, especially when there are too many packets to deliver. This is because the architects of the internet protocol weren’t aiming to reliably deliver data, they were trying to make a protocol that was tolerant to imperfect networks. By expecting the communication to be imperfect, the system became more robust.
Web standards like HTML and CSS are similarly tolerant. I can write a web page using HTML and CSS with so many syntax errors that the computer can’t understand what the hell I am aiming to do. But the browser doesn’t (usually) crash and the user isn’t presented with a bunch of indecipherable compiler warnings. The browser does what it can, but makes no guarantees that it’s got it right.
Beyond tolerance to imperfections, there is also the concept of making something ‘imperfect, but useful’ by design. Images stored in JPEG format, for example, can be compressed to phenomenally small sizes by storing an imperfect representation of an image. That sounds ghastly to perfectionists. In reality, I don’t care whether my readers see a pixel-perfect representation of my visit to Death Valley. I can usefully convey some impression of Death Valley with an imperfect JPEG image. Perfection often comes at a cost; it is better to make something useful, however imperfect.
After mulling it over, I have decided on the following principles for future designs:
- Backwards compatibility because not everyone will switch to your new widget
- Cross compatibility because there’ll always be a competing widget
- Forwards compatibility because someone will eventually design a better widget
- No assumptions about the environment because the widget will inevitably be exposed to an imperfect/unexpected environment, including untrained users
- Imperfect by design, but useful because something should be useful if it exists (a topic for another day), and we rarely require perfection in design
It is not my intention to berate the pursuit of perfection, justify lazy design, nor extol unnecessary complexity for the sake of some arbitrary design criteria. I am simply suggesting that we tolerate imperfection in design, both in what we make, and in what others have made.