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.

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.

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.

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.

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.

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.

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.

It's true that SICP is better written, and has a lot more mindblowing insights, but Code Complete covers a lot of practical stuff that SICP sort of hopes you will learn from your own experience. I recommended them both in my talk at UBV last year --- http://pobox.com/~kragen/talks/2006/ubv --- and I guess my summary of the difference is that reading SICP will make it possible for you to write programs you couldn't have imagined writing before, but reading Code Complete will add a lot of comprehensibility and correctness to programs you could have written before.