I am a terrible programmer. Does that mean I'm bad at programming? I don't know, I think I'm pretty decent. I write regularly in three languages and can find my way along in another dozen. I indent four and wrap lines at 78 characters. I write my own development tools. I document clearly. I carefully consider class layouts. I regularize programming interfaces. I sanitize inputs. I employ test suites. I'm fastidious about version control. I package for distribution. I account for dependencies. I'm steeped in design patterns. When it comes to security, I hit the sweet spot between paranoia and efficiency. I've even permitted past employers to label me senior and pay me a high salary for the privilege. But I'm still a bad programmer, because in order to be a good programmer, I have to do something I have very little tolerance for: produce industrial quantities of code.

I don't like writing lots of code because I believe it's bad for my physical, mental and social health. I also find it tedious and boring. And in over a decade of researching around and working with software professionally, I have come to the conclusion that it is largely unnecessary.

What Software Is

My definition of software is a business process that is defined with enough specificity to be implemented as a machine, taken to its logical conclusion. This conclusion being, of course, to design a machine that executes designs of machines, thus cutting out the expensive process of manufacturing or constructing the latter.

Yet, ironically, our language for discussing the acquisition of software is still couched in terms of manufacturing and construction. This is a topic for another day, though.

But a business process is a conceptual thing: it's a series of steps that reliably produces a predictable result✱. The content of the steps is significant, not their quantity. A given process requires not one iota more or less than the exact amount of language required to describe it. Which means under ideal conditions, for a particular process, I should only need to express it in code exactly once.

✱ I'm intentionally using a broad definition of business process—any goal-oriented process is a business process. Tying your shoes could be a business process if the goal was to tie your shoes, It has nothing to do with actual business except that actual businesses have to produce effective results if they want to exist. Additionally, I only mention it above in the context of an algorithm, though a process that achieves effectiveness by aggregating unreliable processes, i.e. a heuristic, could be a business process just as well. The physicists tell us everything works that way anyway.

I'm On a Boat (of Theseus)

It's at this point that people usually complain to me that this is an unrealistic expectation, because requirements are continually changing and new information is being exposed. For the record, they usually do it condescendingly, as if I was somehow deficient, or had never done real work before. It's unfortunate to be so unimaginative. Consider the following:

Software is made of language. Language is made of symbols. Symbols have meaning. A symbol may be composed from other symbols to create a composite meaning. A symbol may also possess a detailed anatomy of smaller symbols, all the way down to the difference which makes a difference. All or part of one symbol may be isomorphic (have an equivalent meaning) to all or part of another symbol, even if it has a different shape. Where this equivalency is not the case, changing the shape of a symbol also changes its meaning, which is equivalent to minting a new symbol.

Given this, we can consider a description of problem P as one symbol, and the code that implements its solution S as another symbol. But the thing is, P doesn't change when the real world changes as much as it is replaced by a description of another problem, Q. Its concomitant solution is no longer S, but T. Physical stuff changes, to be sure, but we aren't working with physical stuff in any more capacity than is required to represent our symbols. And that, my friends, is key.

The Isomorphism Shuffle

The issue I have with code is that as a medium it is too damn precise. You simply can't operate over any concept until you have defined it exactly, whether or not it exhibits any fidelity to its referent. Then there are the myriad considerations peculiar to the implementation. It's like digging the Panama canal with a toothpick, or with recent advancements, a chopstick. Some might boast that as a fourfold performance improvement, but that isn't good enough for me.

Software code is almost at the very end of a long chain of transformations between symbols that begin in your head and terminate in the transistors of a microprocessor. The almost is significant, because it's those last few links in the chain that make the practice even remotely close to manageable, and offer a hint to make it more so. I'm speaking of course about compilation (or interpretation), assembly, and the translation of machine code into microcode. The only way this can produce predictable results is if the coarser, more palpable symbols are isomorphic to collections of the finer, more arcane ones. So my question is why don't we put more effort into extending this chain in the opposite direction? So we have an unbroken line of isomorphisms, punctuated by representational artifacts, that go from the mental model of the system's designer all the way down to the silicon?

Now, a few people have tried to bolt another layer of abstraction onto the human-touching side of code, usually as some sort of graphical interface. This is interesting, but has yet to add all that much to the pliancy of its semantic structure. The meta-discipline collectively known as user experience design has come from the opposite direction, clarifying and enhancing mental models to attempt to reconcile them with a viable implementation. But there is still a gap, and it's significant.

Of course code needs to be written in order to create a software product. That's tautological. To hesitantly revive the construction metaphor, it's like saying you can't have a building without building a building. But that doesn't mean you should immediately run down to the job site and start laying bricks and pouring concrete. That isn't an indicator of performance, it's an indicator of lunacy.

So What to Do?

My advice? Make representational artifacts that are no more specific than the information available to describe them. If you can express it specifically, it isn't necessary to race to coerce it into a product. It's arguably more important to reify a solid concept than it is to deliver product, as they say, on an early and continuous basis. That just puts you on a treadmill.

What is a representational artifact, you ask? I can't tell you, because it's different every time. It's whatever it needs to be in order to convey a desired meaning, made out of whatever medium or media most appropriate for doing so. Like a pencil sketch, or a clay model, or a video of an interpretive dance. Code is a representational medium as well. If you experiment with different media, you will find that some afford certain forms of expression with greater ease than others. The process of acquiring software doesn't all have to happen on a computer and it certainly doesn't have to be expressed exclusively in code.

Of course, the least desirable scenario is a monolith. For a solid depiction of a robust approach, read the parable of Tempus and Hora near the end of Herbert Simon's The Sciences of the Artificial.

If you hold one less-specific representational artifact in one hand and a more-specific one in the other, you should be able to look at both and say with confidence whether or not they are conceptually identical. You should be able to say if one lacks features significant in the other, or if it possesses extra features which would otherwise change its meaning. In order to do this, however, you need to sufficiently understand both.

And that, my compatriots, means thinking about where we draw the lines between professional disciplines and how we divide labour. Another topic, perhaps, to explore another day.