Software Architecture/Design Ruminations

Last updated: 10/27/2003.



Over time, I've become more and more opinionated about good design and architecture, as it's become clear to me it often makes the difference between something being usable only by experts (or the otherwise well-trained) and being used by everyone because nobody even thinks about it.

As a professional engineer, it's become a point of almost painful embarassment at times. Consider the blinking 12:00 on nearly every VCR, including mine; a thing that people can't be bothered to fix because it's just hard enough to do that nobody will go out of their way to do it. This one is so famous it's entered the culture.


There is a book written by Donald Norman called The Design of Everyday Things (can be easily gotten from various online booksellers, BTW) which has deeply influenced my design and architectural work. It talks about things like the design of doorknobs, telephones, and faucets, as well as the categories of ways that humans make errors.

In particular, it talks about why good design matters, and how people react to good design vs. bad design. It's more than just "easier to use"; it's often the basis of whether many people will even try something in the first place.

To make a long story short, over time I've come to realize that it's not just User Interfaces that need to be made intuitive and simple, but all interfaces. APIs, instruction sets for processors, computer languages, hardware bus definitions, etc. all fall into this category.

The Naive Thing is the Right Thing

Toward this end, I've been developing a philosophy for API design that I call "The Naive Thing is the Right Thing", by which I mean: With a well-designed API, the obvious simple way to perform a task should also be more-or-less the correct/best way to do it. So, the simplest way to program something should have, say:

There is a common maxim in the software world that you have to write a program 3 times before it becomes mature. I have come to think a non-trivial amount of this is because the programs are written using APIs that usually have none of the above properties.

My poster-child example of an API which does not fit this category is one of the aspects of the original *NIX system call interface, specifically the concept of the EAGAIN return code in some functions that can block. Note that this is not a failure code; it can happen during normal correct operation and simply means you have to "Call again later". Some modern *NIX variants have fixed this, but for portable code it still must be supported.

...[include other examples here, plus find positive examples]...

Interface Drift is Bad

The interfaces I'm talking about are APIs, instruction sets, hardware buses, etc. Most of which seem to "Drift" over time causing Bit Rot of ...

...[Talk about "Embrace and Extend" and why it's also bad]...

...[include other examples here, plus find positive examples]...


Obviously Correct Design

Fundamentally, this concept is about the idea that the best designs are ones whose correct implementation can be easily distinguished by just looking them, i.e. the very nature of the algorithm makes it much more obvious when it is correct or not.

...[include Knuth example here]...