Ender’s Game is one of my favorite books. It’s not exactly the pinnacle of human literary achievement, but Ender’s Game and it’s parallel novel, Ender’s Shadow, both have really good story lines and powerful characters. I think they are books that everyone should read at least once. In particular all programmers should read both of them.
Though the book is about children who are fighting a war for humanity’s survival, it’s also about soldiers learning to be generals and all-round leaders. At first read, it doesn’t seem to have anything to do with programmers. But a few months ago I read an OSNews article about the problem with design and implementation of software. After sitting in the back of my head and germinating for the past few months the one paragraph that came back to me last morning is:
The major problem with this is that ALL of software is design. 100% of software is design from the high level architect-like design to the low-level design of a for-loop. The implementers of software are not human! I knew you suspected as much given how odd many programmers are. No, the implementers of software are actually ‘perfect’ machines. They are the compilers (interpreters, preprocessors… are all included in the generic use of the this word). For almost all purposes, the compiler is perfect. I’ve yet to run into a situation where I’ve written code and the compiler has not followed my instructions and that is the reason something broke. It hasn’t happened yet.
One of the core themes of Ender’s Game and Ender’s Shadow is how the main character, Ender learns to become the commander of an elite fighting force. This force is special because unlike other commanders, Ender trusts his soldiers and gives them the independence to develop their own strategies and techniques. What I realized is that just as Ender is the commander of his fighting force programmers are the commanders of their own programming forces. Instead of having snipers or demolition experts, we have our compilers and source control systems. And like Ender, we must learn how to use your teams well and get the work done.
As programmers, especially novice programmers, we tend to anthropomorphize. A lot. Often enough we say things like “My program isn’t doing what I tell it to do” or “My program is misbehaving again”. In many ways, anthropomorphizing is a coping mechanism: it gives us a comfortable way of thinking about something that is very different from most other things we experience in life. While it might help us to think about computers and programs in human-like terms, it can also be a pretty limiting point of view.
The OSNews article above is about how thinking in terms of separate implementation and design phases is detrimental to writing quality software. The “perfect machines” idea that he talks about is an argument against the way we humanize computers. Because we think about our programs as people, we assume that they make mistakes just like people do. We assume that our programs aren’t doing what we want because they don’t like us or that they’re just misbehaving. I’ve been programming for a good few years now and I find myself falling into this trap more often than I would like. However, the truth is that we’re not dealing with people: we’re dealing with perfect machines. A mistake in our program is much more likely to be our own fault than it is to be a problem in the compiler or libraries.
Just as Ender learned to trust his soldiers to act on their own under battle situations, we programmers need to trust our machines. We need to understand that our machines are right, more often than not. Sure compiler errors aren’t perfect and it sucks when GCC spits out three pages of errors to tell you that you missed a semicolon, but that doesn’t mean that your program doesn’t “want” to compile. It’s not easy, because the world of computers is really very different from the world of people and thinking of programs in “people terms” helps us form a bridge. But like all such bridges, this one is ultimately a set of training wheels which we need to lose. And you can’t ride a mountain bike if you’re not ready to lose the training wheels.
Personally, I’m going to try to make a conscious effort to not blame the machine when something goes wrong. Problem-solving is what we do as programmers and it would really help to look in the right place. The right place is in my program because I can trust that my troops have done what I’ve told them what to do and if things are going wrong, it’s because I’m telling them to do the wrong thing. I could go on waxing eloquent about how we need to take responsibility for our programs, but I think I’ve made my point. Our implementors are perfect machines, but we’re certainly not perfect and we need to keep that in mind.