Some thoughts on minimalism and programming languages

Like a lot of programmers, I’m a big fan of Johan Sebastian Bach. During a stop-over at JFK airport a couple of months ago I met a charming and talented concert pianist named Lisa Yui. We talked about music, and something she said about Bach resonated with me. Paraphrased, she said “His music is very precise; not a single note is unnecessary.” It’s true; despite being a Baroque composer – an era renowned for its ornate, decorated architecture and art – Bach’s compositions are remarkably restrained and, if I may say so, minimalist. The best programmers I’ve known prize minimalism and simplicity. The simpler the design, the less that can go wrong. Maybe that’s why programmers like Bach.

01_Aria.mp3 Listen to this

(nb: at some point in writing this article it became “Why I like Go,” – if that offends you, stop reading now!)

No tool can force you to be a minimalist. While you can be a minimalist in any language, they each have their philosophies, and these shape the way programmers think.

C – the B language with the addition of types – is essentially a portable assembly language. While that in itself is minimal, doing even the simplest things with dynamically-allocated data structures necessitates a lot of bookkeeping that is hard to abstract away. While there is some beautifully constructed C code out there, it’s often hard for me to distinguish it from the arcane.

JavaScript has a minimal feature set and standard library, but it is encumbered with the weighty, organically-designed, and ugly DOM API. It has also suffered at the hands of the browser vendors, leading to inconsistent and strange language features that behave inconsistently across platforms. I’ve written upwards of 50k lines of JS in my career, and there were times when I thought I was being very clever indeed that, in retrospect, were just examples of horrible code. (I don’t think I’m alone, there.) This, combined with the fact that it’s mostly used for callback-driven UI stuff, makes most JS code a big bowl of spaghetti. (Simpler environments like node.js allow JavaScript’s finer qualities to shine; I should make a note to take a look at some large server-side JS programs.)

Java’s language design has a marked effect on the code people write. I find it almost obscenely bureaucratic at times. The Java enthusiasts I know insist that a lot of this is a cultural problem, not one inherent in the language. I’m inclined to agree, but, even so, on the occasions when I’ve chosen to use Java I’ve found it very hard to keep the design simple. It’s just so much easier to add some methods and properties to a class than to create a new class entirely, even if the latter is what a simple design dictates.

Python is a great language, but what I find troublesome about it is that there are so many ways to do things. If you’ve spent any time working with Python, you know what it’s like to read through someone else’s code and be totally confused, even in the “coding in the small” sense. This problem is even worse in the Lisp family of languages, where a good programmer can get a hell of a lot done, but good luck having someone else understand how it works. (This is probably an unfair characterisation.)

Haskell, OCaml, Erlang, and others have their own style. From the code I’ve read, they’re pretty nice. But I don’t have enough experience using them to say much about them.

Go sits in this interesting middle ground. It’s statically typed, and not really very dynamic, yet it’s quite expressive. You get a lot of the benefits of these dynamic languages (like closures, succinct variable declaration), but there’s some enforced structure and style in there, too. There tends to be only one or two ways of getting things done, so reading other people’s code is generally pretty easy. Being able to concisely define new types (and methods on those types) means there’s no incentive to building monolithic swiss-army objects. Simplicity is inherent in the language features, and it brings out the minimalist in me. And I like that very much.

This has been a largely unstructured collection of thoughts. I’ve just spent the last few months talking to people around the world about programming languages, and I’m fascinated to hear other people’s thoughts on these topics. Please comment!

14324 views and 6 responses

  • Jul 11 2010, 1:56 AM
    Sergey responded:
    Things start to work and become successful when they become simple. Just a few examples from IT:
    the first what is called to be a computer - the Analytical machine of Charles Babbage - it used 16-bit numbers (please correct me - I am not sure at this point). And it never worked. Only when simplified to binary computers started to work.
    LDAP (Lightweight Directory Protocol) - used in most enterprise authentication systems - it is based on X.500 specification. X.500 specification never worked because was too complex to implement.
    HTTP (HyperText Transfer Protocol) is based on SGML, as well as XML. SGML never worked, because was too complex.
    UNIX - castrated MULTICS. MULTICS was a very advanced operating system designed in the 60-s. It never got widespread adoption because of its complexity.
    Please add more examples ;)
  • Jul 11 2010, 2:07 AM
    Andrew Gerrand responded:
    "Perfection is not when there’s no more to add, but when there’s no more to remove."

  • Jul 11 2010, 2:19 AM
    Sergey responded:
    I fully agree.
  • Jul 13 2010, 5:03 PM
    Marce Conroy liked this post.
  • Jul 27 2010, 5:30 PM
    Adelein Rodriguez responded:
    I came across your post and this bit about Bach has always fascinated me too. Check out this book, it talks about the mathematics and patterns behind his music, among other things. It is called Gödel, Escher, Bach: An Eternal Golden Braid, Enoy!
  • Jul 27 2010, 8:40 PM
    Andrew Gerrand responded:
    I've read GEB/EGB - it's a real classic!