At CodeMash Neil Ford gave a keynote about polyglot programming, a subject about which I’ve been thinking a lot — and a subject which I have a slightly different (and somewhat more pragmatic) set of opinions than Neil expresses.
But, at the moment I’m hung up on a throw away section of his talk which I think indicates a misunderstanding about the way language and metaphor work. A misunderstanding which is probably particularly common among programmers, but which goes to the heart of why I think software development is so difficult.
Niel takes exception with the notion that software development is software engineering saying something along these lines:
It’s not true. It’s a metaphor. In fact, it’s a ‘tortured’ metaphor. Software and engineering really are different. What we need is to get away from these metaphors, since they cloud the issue, and describe what it is we actually do.
He goes on to say a lot of interesting stuff about how engineering is different than software development, which is of course true. But I think that misses the point a bit. Methaphors aren’t supposed to be flat descriptions of fact. If I say “I’m as tired as a wet dishrag” nobody expects that they could measure my metabolic state against that of the dishrag and determine the “truth” of my statement. It’s true in a very different way. And I’m not just talking about creative language, or artistic merrit. Truth in this case is all about explanatory power.
Natural language is imprecise, analogical, and metaphorical — and after 4 years of philosophy, linguistics, literature, in school and 10 years of software development I’m convinced that these aren’t just surface traits of most language, they are the fundamental constructs from which all human language interactions are built. And, more than that I’m certain that this is actually a good thing, because the world is filled with things that we can only talk about that way. But I’ll get back to that in a second.
First, let’s dive into why I think Neil is wrong, and why I think his error is the kind of error that programmers are particularly prone to fall into.
Programming is both more abstract and more concrete than natural language. As Ocean tells us:
That there are no metaphors in programming, that there is zero ambiguity and every single line of code always has a definite, unambiguous, unarguable, and precise meaning has a very important consequence: integration is extremely difficult. Unlike poets who can take practically anything and throw it at the page and make it stick with a bit of jiggling and handwaving, a programmer must speak in a language that a computer can understand — ultimately, in 1′s and 0′s! And so it’s almost impossible to seamlessly combine programs to create new programs.
Every line of code has a specific well defined meaning. And unlike language that meaning is not the internal subjective representation of the code in the reader’s mind, nor a shared but nebulous social construct. It’s totally external and absolutely quantifiable. Code is defined by the way in which it will be parsed and executed by a pile of silicon.
Natural language is totally different.
One of the most influential philosophers of the 20th century, and very smart dude — Ludwig Wittgenstein — reminds us, it’s very hard to define many words even though everybody knows what they mean. The famous Wittgenstinian example is the word game which applies to things like ring-around-the-rosy, professional football, chess, World of Warcraft, hopscotch, and solitaire. The important thing to notice about this example is some games are played competitively, and others are not, some have well defined rules, others do not, some are frustrating and complex, others are simple and fun, some are professional, and others are done for pure pleasure.
You might suggest that there’s some core idea of amusement involved in all games, but that begs the question what is amusement? How could it be the same for children playing duck-duck-goose, football players at work, and chess masters practicing.
But the most important thing to remember is that even with all these “complications”, it’s obvious to everybody what we mean when we say game — even if they can’t provide an adequate working definition of “game” that actually covers all the things we commonly call games.
As I understand him, Wittgenstein, goes further to suggest that it is the lack of logical rigor, this tendency towards analogy and metaphor, this embrace of ambiguity that makes language useful. I think that’s very much true. Without ambiguity and metaphor we couldn’t communicate complex new ideas, and we couldn’t extend our base of knowledge from one area to another, and we would be entirely unable to communicate anything about huge swaths of human experience at all.
Back to programming. Program languages can’t express love, or disdain, there’s no such thing as irony. There’s no way to say anything meaningful about art or love or spirituality. It’s all concrete instructions that operate in a well known context. So, I see what Ocean is saying when he argues that programming is more concrete than natural languages.
But at the same time, I’m convinced that software development is all about creating systems that encapsulate various kinds of complexity. Another way to say that same thing is that software is all about building up layer upon layer of abstractions, and software debugging is all about the complex process of learning to traveling up and down the “abstraction stack.” And the terminology in software development is all divorced from any easy-real-world referent, “objects” aren’t physical, “stacks” and “heaps” don’t really “take up space” and memory “locations” are only metaphorical. The layers of metaphor requires to say the simplest thing about software development can be enormously daunting. In contrast with natural language it’s so easy to see the relationship between the word “pencil” and the real world object it represents.
So, software development is inherently much more abstract, and is often almost completely divorced from the concrete referents that make up everyday language. Which means it makes lots of sense to say that any kind of reasonable discussion of the the act of programming is ultimately less concrete than most natural language, as is any discussion of the code. And, really what else would you expect from a discipline build around building abstractions and encapsulation of ideas in executable forms.
Ultimately good programmers build up metaphors which provide layers of abstraction which are effective presisely because they offer a non-literal way of talking about the complex things that happen “undernieth” that layer. Take away the metaphors, and you won’t be able to talk about what you do. You won’t be able to explain what you do to other programmers, and you won’t be able to think lucidly about the problem domain and the code at the same time.
All this is the very long way round to saying that programming requires all kinds of mental tricks, and that ultimately talking about writing code is going to require metaphors. With all respect to Niel Ford, the problem is not that we use metaphors, it’s that we don’t understand how to use metaphors well. The more metaphorical our metaphors are, the better, because then they aren’t easily taken for flat descriptions of fact. As far as I am concerned, Software Development is like Engineering, but it’s also like washing windows on a skyscraper, playng chess, or trying to understand what language your teenage daughter is speaking.
Fundamentally I’m convinced that learning to do software development really well is about learning how to communicate really well. And communicating really well means working at the level of metaphor and analogy because the problems, requirements, and users of your system all operate at this level. It also means learning to translate that into code which expresses the metaphors that help people solve their problems in a medium (code) that has zero ambiguity, but to arrange that code into systems built around sensible — and easily communicated — metaphors.