Why Software Development isn’t Like Construction


In “Code Complete”, Steve McConnell says software development is like construction. In this article, I disagree.

Code Complete

Steve McConnell’s “Code Complete” had been recommended to me by several people whose opinions I trust, so I was looking forward to reading it. It’s a substantial and well-researched book based on the premise that software development is like construction — indeed the subtitle of the book is “A practical handbook of software construction”.

I didn’t like it.

In a book of this size which dares to discuss — in some depth — sensitive topics such as code layout, naming conventions, editors, and the relative merits of programming languages, I’d expect to disagree with the author on a few details. That’s all part of the fun of engaging with a book. In this case, though, the central theme of the book turned me off: software development isn’t like construction, or at least it shouldn’t be. The metaphor is a dangerous one.

Metaphors for software development

McConnell’s claim isn’t surprising or novel. Indeed, perhaps the most common metaphor for the process of software development is construction. Thus software architects design the software, project managers organise resources and keep a check on costs and timescales, and software engineers get on with doing the actual building. Well written software has a discernable structure, as does a building. And so on.

McConnell devotes Chapter 2 of Code Complete to a discussion of metaphors in general and metaphors for software development in particular. He notes software development is a young field and that consequently there’s no standard set of metaphors. He therefore goes on to evaluate a list of the more common ones.

  • software penmanship: writing code
  • software farming: growing a system
  • software oyster farming: system accretion
  • software construction: building a system

Writing and growing

The writing metaphor is quickly dismissed. It doesn’t really tell us much. Well of course we write software. Similarly, the farming metaphor has little to offer: farmers can’t arrange for favourable weather, but we have greater control over the factors affecting software development.


McConnell approves of the “oyster farming” metaphor, but it’s the point at which I started to question his opinions. He says:

Accretion describes the way an oyster makes a pearl, by gradually adding small amounts of calcium carbonate … Other words closely related to accretion are “incremental”, “adaptive”, and “evolutionary” … You first make the simplest possible version of the system that will run … You add a little code at a time until you have a fully working system.

I think this is a misrepresentation of incremental software development (a technique I favour). Yes, the idea is to start with the simplest possible version of the system, and to gradually add to this; but the important point is to have a fully working system at all stages, and to continually review the plans for this system. In this way, we keep the software malleable and can deliver what’s really of most use, and can continue to make such deliveries in future.

Incremental software development doesn’t look to deliver a shiny, hard, pearl. We’re aiming for something more flexible.


McConnell suggests the image of building software is more useful than that of writing or growing, and that it’s compatible with the idea of accretion while providing more detailed guidance.

For example: just as constructing a shed merits a different approach to constructing a sky-scraper, so constructing a simple program is different to constructing a sophisticated software system.

He elaborates:

Greater complexity and size imply greater consequences in both activities … Ripping out a wall and moving it six inches is expensive … To move a wall six inches costs more if the wall is load bearing than if it’s merely a partition between rooms.

Software is soft, buildings aren’t

There’s some truth in what McConnell says, but I still think the software-as-construction metaphor is misleading.

A building is solid, physical, heavy. You can’t pick it up and move it. You can’t push it down a wire. You can’t clone it. You can’t replicate bits of it for reuse. You can’t really reconfigure it. You can’t put the roof on before you’ve built the walls, and you’re in trouble if you decide you want to deepen the foundations once the building is finished. As McConnell says, simply moving a load-bearing wall six old-fashioned inches is expensive.

A computer program is less tangible, more intellectual. It comprises, quite literally, a set of written instructions.

We describe software which performs well as solid and resilient, but really it’s fluid and supple. Software should be soft. You can copy it with one action and erase it with another. And it’s never really finished in the way a building is.

A well written program builds upon layers of abstraction. By designing the layers correctly, they can be modified independently: changing the memory management layer should be no more difficult than changing the user interface. If we find ourselves struggling to move a load-bearing wall, it’s a sign we’ve gone wrong.

A better metaphor

McConnell rejects the software-as-writing metaphor for good reason, but if we look again, it can point us in the right direction. Software development is writing. It’s communication: between the developers on a team, between the team and the machine.

The layers of abstraction I mentioned in the previous section are linguistic. Each layer is interpreted using the language of the layer below.

“Structure and Interpretation of Computer Programs”, a more profound and ambitious investigation of the art of computer programming than “Code Complete” — a better written book — has this to say.

We must constantly turn to new languages in order to express our ideas more effectively. Establishing new languages is a powerful strategy for controlling complexity in engineering design; we can often enhance our ability to deal with a complex problem by adopting a new language that enables us to describe (and hence to think about) the problem in a different way, using primitives, means of combination, and means of abstraction that are particularly well suited to the problem at hand.


To appreciate this point is to change our images of ourselves as programmers. We come to see ourselves as designers of languages, rather than only users of languages designed by others.