Production lines are inspiring things; row upon row of machines moving in perfect synchronisation, churning out products with speed and precision. It's easy to see why it would be nice to have our software development process work the same way - fast, accurate and efficient. While there are useful lessons to be learned here, it's also important to remember the ways that building software is not like building cars, and to note the pitfalls inherent in trying to treat it as such.
We Start Without Blueprints
When you first power up a car factory, before a single robot has so much as moved, you know what the cars are going to look like. You have to - you can't program a robot to build something unless you know everything about the thing it's going to build. Every bolt, every rivet, every component has already been designed, and somewhere there's a big set of diagrams explaining how it all goes together.
Software development is not like that.
When we build software, we don't know precisely how every part of it will work. We don't necessarily know what parts it will have. In some cases, we don't even know exactly what it needs to do - the process starts with requirements capture, including discussions with customers or product owners, mockups, prototypes and A/B testing, and a whole load of other techniques that aim to work out what the customer actually wants from the software. Armed with that information, we can then start defining acceptance criteria that will be used to determine whether our software satisfies those requirements, and only then can we start writing code. In an organisation that uses an iterative development methodology, we may start writing code as soon as we have a clear view of a part of the requirements, and use the resulting prototypes or minimum viable products to help us discover the rest. Car manufacturers don't tend to give their customers a car consisting of a bare chassis, wheels, and an engine in order to help them decide what sort of seating or bodywork is needed, but that's roughly how software development often works.
What Is The Blueprint For Software?
Imagine a document that explains everything that a piece of software has to do. I mean everything, in perfect clarity, with no ambiguity, to the point where it could be followed with no independent thought required and the result would do absolutely everything the software is meant to do, without error. While it would be nice to believe that our acceptance criteria could be such a document, that's often not entirely true, and with iterative development the acceptance criteria are written as we discover each new requirement, meaning that the product is mostly finished by the time we've written our last set of acceptance criteria. Even then, they're written in natural language, which brings with it all the ambiguity, inconsistency, and opportunities for miscommunication that English (or whatever your native tongue) has built-in. A truly perfect specification for an application's behaviour would have to be written in a structured and self-consistent language, where there can be no ambiguity.
There is one point in the software development process where such a document exists, of course. That point is the very end, and the document in question is the source code. By definition, a programming language can be used to define behaviours in such a way that no thought is required to follow them - because that's precisely what a computer does. This makes it clear that software engineering is not analogous to the process of building a car - it's much more like the process of designing a car and drawing up the plans that the production line will follow.
So Where Is The Production Line?
If source code is the blueprint, then does that make the compiler our assembly line?
In a manner of speaking, yes. In fact, there is a significant part of the effort in delivering software that happens after you've written the code. There are builds, tests, deployments, and a whole raft of processes to follow to get the software into the hands of users. This work is repetitive, predictable - and frequently automated. Automated tests, continuous integration builds, automated deployments; they take in our blueprints - the source code, the build scripts, the configuration files - and follow exactly the same process every time, to churn out identical copies of the product we designed. These are our production line.
There are valuable lessons that can be learned from examining how production-line processes work, and how they have been improved. Lean and Kanban came from this kind of environment, and have been applied to software development with great success. As with many things in our industry, the comparison to a similar process can be instructive and illuminating - but it can also be misleading in places where the metaphor does not fit. When using comparisons to model a domain, remember to be alert for areas where the model is a bad fit, and don't try to hide complexity or nuance for the sake of an attractive metaphor.
Comments powered by Disqus