Assembling software: Industrial Style
The origins of lean thinking lie in production and there’s quite a bit of interest in finding parallels between current software development practices and those of manufacturing. The Poppendiecks for instance, frequently quote examples from classic manufacturing companies (Ford, GM, Dell, Toyota) to help understand why agile methods are a very effective approach to software development. Oddly enough they (and many, many others) are hesitant to buy fully into the concept that manufacturing industries and software development have indeed much in common.
Early in their book “Lean Software Development: An Agile Toolkit”, it says:
“However, lean production practices -- specific guidelines on what to do -- cannot be transplanted directly from a manufacturing plant to software development. Many attempts to apply lean production practices to software development have been unsuccessful because generating good software is not a production process; it is a development process.
Development is quite different than production. Think of development as creating a recipe and production as following the recipe. These are very different activities, and they should be carried out with different approaches. Developing a recipe is a learning process involving trial and error. You would not expect an expert chef's first attempt at a new dish to be the last attempt. In fact, the whole idea of developing a recipe is to try many variations on a theme and discover the best dish.
Once a chef has developed a recipe, preparing the dish means following the recipe. This is equivalent to manufacturing, where the objective is to faithfully and repeatedly reproduce a "recipe" with a minimum of variation.”
Well, Tom and Mary, allow me to disagree! The main purpose of the modern assembly line is not to produce masses of the same good “with a minimum of variation”. Actually, for car manufactures this is about as far from the truth as it gets. The Mercedes-Benz assembly lines in Sindelfingen near Stuttgart for example, produce hundreds of thousands of variants of the C-, E- and S-class. There are about 8,000 cockpit variants and 10,000 seat variants for the E-class alone; there are almost certainly no two identical cars rolling of the lines on the same day. What starts of with me (if I were a Man of the Three-Pointed Star) ordering a car at the dealership results in an enormous logistic and organizational effort to get the right components to be available at the right place and at the right time on the assembly line (with suppliers supplying the right parts at the right time to minimize storage costs). Raise your hand if this fits with your idea of a “recipe with a minimum of variation.”
Software engineering lags more than a century in maturity behind manufacturing; it is really more like a cottage industry handcrafting one-of-a-kind solutions than proper engineering. The current practice in component-based software engineering amounts to getting just the individual parts necessary to assemble a single car. Some of these parts are not a perfect fit, and some cutting and filing is needed to make them fit (i.e. adapt them) and some parts are purpose-developed for this one car. And even if a library of elementary, designed-to-fit components is present (‘no cutting and filing required’), these still have to be assembled manually and there’s still a lot of detail to consider in the process.
Compare this to ordering a ready-made car by describing it in abstract, solution-oriented terms, stating only as much as is really needed: “Get me a SLK 55 AMG, shod on 18” wheels, with chromed exterior mirror housings.” And that’s what I would like as a programmer: stating what I want in abstract, solution-oriented terms and have the desired system or component produced in an automated fashion.
If this sounds all to magical, it is really a paradigm for software engineering based on (i) designing implementation components to fit a common architecture, (ii) the configuration knowledge linking abstract requirements to specific constellations of such components, and (iii) implementing this configuration knowledge in an automated fashion. These steps are what happened to car manufacturing as well: the principles of interchangeable parts (Hall, 1826) led to the introduction of the assembly line (Olds in 1901 and refined by Ford in 1913), and automation using industrial robots in the 1980s.
Not convinced yet, let me end with the inevitable referral to Ruby on Rails. It may not be on the level of true manufacture, but here’s too a way of specifying a system (‘family member’) in terms of constructs of a higher level of abstraction (‘has_many’, ‘validates_presence_of’), a set of implementation components (‘ApplicationController’) and generators to tie everything together (‘./script/generate’). And boy does it work. Beautifully. Just imagine what the next step will be like!