Unlike computers, humans tend to think in metaphors. That is, when we want to reason about something new or unfamiliar we reason by analogy with something familiar. This is a great mental trick and it is part of what allows humans to be flexible and to deal with unanticipated circumstances (exactly the kind of thing that computers cannot do), but there is a danger as well: where the analogy chosen is not a close match, our thinking can be led astray. One place where these analogies are often poor is in thinking about the process of programming.
Programming is like doing mathematical proofs.
Before the field of programming really came into existence, there was a metaphor for it: programming was like doing mathematical proofs. And before the invention of the electronic computer, it was a fairly good metaphor. After all, the first practical von Neumann machine wasn't built until 1949, while Turing and Church were busy inventing the mathematical foundations of computer science in the early 1930s. The metaphor accurately captured the sense that programming required the same sort of logical precision as a mathematical proof. But it misleadingly implies that programs are perfectly error-free (most of us are not Knuth), that creating them is a solitary process, that they are inaccessible to all but the brightest minds, and many other misleading implications. Fortunately, this analogy has been thoroughly abandoned.
Programming is like writing a book.
The next analogy I know of dates from the earliest days of programming on computers, and it is still with us today in some of the language we use. We speak of "writing" a program, or refer to the "author' of a particular piece of code because one of the early metaphors was that programming was like writing a book.
At a very shallow level, this metaphor is obvious: programming involves typing at a keyboard, just like writing. The metaphor actually has a bit more to offer than that (particularly for describing small programs and one-person efforts). Just like writing a book, the programmer begins with an outline or high-level plan. The programmer then works out the high level details in her head, but most of the details are not determined until the pen hits the page (or keyboard). Much like a book, it is important to have a good high-level structure (plot), but in the end it all comes down to proper execution of the details.
But the writing metaphor is also responsible for some of the most pernicious misunderstandings by non-programmers. It completely fails to capture the way in which the difficulty of programming scales more-than-linearly with the size of the program: writing a book that is 2x as long will take 2x as long but writing a program 2x as long may take 3x or 4x the effort. When poorly informed managers attempt to measure productivity in Lines Of Code, they are being mislead by the writing analogy. The writing metaphor fails to capture the vital role of testing and debugging in programming - which are nothing like editing a piece of writing. And perhaps most seriously of all, the writing metaphor does nothing to describe the fact that programming today is nearly always a team activity.
Programming is like building a bridge.
The "programming as writing" metaphor still lingers in some areas (particularly when speaking about the "lone programmer"), but the essential failure to capture the team nature of software development caused industry to adopt a different metaphor. They needed a metaphor for a large group of people coordinating to create something, and they cared deeply about the processes for measuring this process and making it repeatable; the analogy they chose was that programming is like an engineering project... the construction of a building or a bridge. The language of software projects is strongly influenced by this analogy: we speak of "building" our code, of creating scaffolding to test things.
In many ways, the metaphor is extremely effective. It does a particularly good job of describing the way in which teams of developers are managed. The mechanisms from managing construction projects, from managerial structures to Gantt charts have been applied to managing software projects, with a certain amount of success. The analogy also captures some of the role that solid requirements and good planning play in a software project.
But the bridge-building metaphor also fails in some important ways. One of the things that corporations want most from their programmers is predictability... most would willingly pay far more in time and cost if they could just be assured of predictable delivery. Yet a substantial portion of software projects fail, and it can often be attributed to attempts to run a software project as if it were the building of a bridge. But when building a bridge, one usually follows well-established engineering practices: most bridges follow an existing design. Software, by it's nature, is constantly doing something NEW (otherwise, you'd just re-use the existing code). So problems like code running 100x slower than expected or detailed, or written requirements that bear little resemblance to what is actually needed... these problems are common in programming, yet are not even hinted at by the construction metaphor.
Buildings or bridges have ribbon-cutting ceremonies: the half-built bridge or incomplete building is unusable while work proceeds until a point when the project is finished and the edifice is available. This mindset has led to "big-bang delivery" in software projects... a common source of failure. And after the building is complete, the construction firm goes away -- there are maintenance staff, but that is a different organization entirely. Programming effort don't really "end" in the same way, but mislead by the construction metaphor, many software development projects do "end".
Programming is like gardening.
In The Pragmatic Programmer, Hunt and Thomas propose a new metaphor: Programming is like gardening. I think that this metaphor offers significant benefits... enough that we should begin to make a conscious effort to use the gardening metaphor in our normal conversation. We should speak of "growing" the code, of "pruning" the technical debt, of "transplanting" libraries and of "weeding" out bugs.
The first big "truth" to the gardening metaphor is that gardens aren't suddenly opened to the public on a given date; they are slowly grown over time. Sure, you might host a garden party (marketing push) on a particular date, but that's not the first time a non-gardener views it - there are several individual visitors to the garden before the party.
Also, after you get your garden planted it requires ongoing care; the plants may grow on their own, but they need constant tending. This is true of programming too. One would think that, since software is built from abstract thoughtstuff closer to Plato's perfect forms than to base materials, it would be LESS subject to the ravages of time than mere bridges. Curiously, the truth is quiet the opposite: the Golden Gate Bridge was built 70 years ago and it stands solidly today; end of life for Windows 2000 came in 2005. Software suffers from "bit rot" - the tendency to stop working because of changes in hardware, libraries, operating systems, standards, or other pieces of the environment. A certain amount of ongoing care is needed to keep the software healthy.
There are many smaller ways in which the gardening metaphor bears fruit. Growing a plant in place "incrementally" produces a healthier plant than transplanting, but it takes longer. Different plants grow better depending on the soil quality. Sometimes you have to take out an unhealthy plant so its neighbors can flourish. There is a wealth of useful insight to be gained from this metaphor, and we should give it a serious try.