Brian's Waste of Time

Sun, 12 Dec 2004

Elegance Matters

There is a fundamental difference between programming and science, which, in my opinion, makes programming much more interesting (if less useful?): science has a reality to be relative to. Programming, except in specific realms such as simulating nuclear reactions, creates a useful model of something which does not otherwise exist, compared to attempting to discover a model for something which does exist.

I have recently moved and in packing up stumbled onto a book in a box I hadn't opened in a while, Mr. Hawkings A Brief History of Time. This lead to a ver pleasent morning's (re) read. At one point I stumbled over Hawking's assertion that Newton discovered Newton's First Law. If anyone understands modeling, it is physicists who know their models are wrong, but may be more useful, or more correct than others. To say that Newton discovered Newton's First Law is like saying McCarthy discovered LISP. We tend to say that he created LISP.

Either us programmers are very egotistical folks, physicists are very humble, or we have quite different operating assumptions. I vote for different operating assumptions (though the only really top notch physicist I have met was extremely humble, so it may be the first two). There is a conception in programming, heck in computer science as a whole, that we are creating something new when we write software (or figure out VLIW, or decided binary logic makes the most sense...) compared to a sense in the sciences of discovering traits of an existing absolute reality (unless the existentialists are correct).

I'll bite, and say that I agree with this model of our profession -- it is a useful model to operate on. The constructs we create have no direct correlation, most of the time, to anything physical. They are ideas expressed in a precise language (Erlang, possibly). To a large degree we model physical things: this is both easier to conceptualize for us, and easier to explain to others. However, these models are always interspersed with breaks from the consensual understanding of how the world works -- in order to be more useful.

If we are creating things, instead of discovering things, it pays to be elegant. Elegance is a quasi-mystical quality things can posess. Different people even consider the same thing to be either elegant or abominable (usually this difference of opinion is based on understanding or getting the way somethign is modelled, I suspect). Either way, some things are pretty much universally considered elegant, everything being a file in Unix being a spectacular example. Elegant things tend to be simple, but are sometimes also just plain wrong.

To look at this, consider learning physics in school. Chances are (unless you are much older than I suspect my readers to be) that you learned Newtonian physics in school, even though it is less accurate than Einsteinian. I mean, I am very much a lay person in physics, but even without having just spent the morning re-reading Mr. Hawkings' book I can point out where it breaks down (the edge cases, where do theories always break down?). That said, despite knowing it is wrong, is less accurate than other options, it is still more useful most of the time, so it is what we are taught (and us geeks still tend to drop our jaw when the epiphany that everything makes sense, and math is way cooler than we previously thought (even if we thought it was really cool), hits).

I won't claim to understand relativity, but I think I understand the shape of it, and it is beautiful. Newton's models (to use programmer terminology) are much easier to grasp, and are also beautiful. Both of them are known to be wrong, but (to my knowledge) no new models to replace general relativity have yet been created (except for modeling really small things). Both model what happens in a complex and important real-time system (ha!). Both are very useful, and are widely used, every day.

We can take something from this about abstraction, and maybe learn a couple valuable lessons about the design of large systems:

Elegance comes from internal consistency and the ability for a model to make possible things much broader and more complex than the elements which make up the model. The elegant model may not be absolutely correct, but it is sufficiently correct and it supports itself for the majority of cases.

An abstracted model does not need to be consistent with the less abstracted model. Newton's model provides a significantly higher level of abstraction than Einstein's. The two models are totally different in the fundamental constructs and terms they deal with. Using general relativity to describe the motion of a body is a lot tougher than using Newton's theories, but as you get towards the edge cases, it is also more accurate. Newton's model suffices for the vast majority of cases, but when it doesn't you can use Einstein's model within the same system (the universe). Despite the models being extremely different they play together nicely.

This is where the difference between creating and discovering really kicks in. The only base reality we tend to need to reconcile software with is a relational schema (when it comes down to it, the RDBMS always seems to be the integration point that matters), and this is only for certain classes of software (which tend to be the "interesting" ones as you get paid the most to work on them, in general (quotes on purpose, they are actually usually quite boring, but important for the very interesting thing called income)).

We tend to get into nasty political wars over how these big systems get modeled. There is a famous essay about lossy abstractions which people love to quote as though it came down from the mountain written on stone, which bugs the heck out of me, as if an abstraction isn't lossy, it is useless. Moreover, I finally have a respected scientific analogy for telling this meme to bugger off: Newton's theory is much more lossy than Einstein's, but it is still more useful most of the time. Sure, sometimes you need Einstein's, but when you do you can whip it out and use it. Using Einstein's means that you cannot mix and match the code between the two systems willy nilly, as you only generally whip out E when N breaks down. When you do, you are in the realm of E though, so stop whining about N being lossy.

So, to reconcile the two, a good abstraction is internally consistent and allows the modeling of more complex behavior and systems from a smaller subset of elements. It is elegant. If you need to worry about elements the first abstraction doesn't consider, you may need a very different model in order to have both be elegant, and that is okay, and even good.

Elegance matters because elegance is useful. The elegance of LISP's design makes it possible to apply LISP to LISP, even if SISC (Scheme in Java) is a big fat abstraction of a stack machine (Java VM), which is a big fat abstraction over a register based machine (the G4 in the laptop I am writing this with, which eventually does some bit operations to make these letters appear).

David Heinemeier Hansson recently tied this to philosophy nicely:

brianm:     nextangle: I think ruby is designed to be intrinsically 
            cohesive and pretty, and good programmers just think that is the 
            gosh darned prettiest and nicest thing
nextangle:  The mistake is to think that pretty and cohesive are 
            shallow values
nextangle:  When they indeed are of the outmost importantance

nextangle:  I think it shares a lot of resemblance to Beauty being 
            the same as Truth in old Greece..

and Kathy Sierra (what a fantastic bio photo, considering the gist of her books) recently posted a similar strong argument that you should care about things being cool. I am roughly of the opinion that elegant things are like black, which for some reason is always cool.

1 writebacks [/src] permanent link