Code evolution raises several practical problems that can be
major sources of friction and drudgery — thus a serious drain on
productivity. Every moment spent on these problems is a moment not
spent on getting the design and function of your project right.
Perhaps the most important problem is
. If you make a change, and discover
it's not viable, how can you revert to a code version that is known
good? If reversion is difficult or unreliable, it's hard to risk
making changes at all (you could trash the whole project, or make many
hours of painful work for yourself).
Almost as important is
know your code has changed; do you know why? It's easy to forget the
reasons for changes and step on them later. If you have collaborators
on a project, how do you know what they have changed while you weren't
looking, and who was responsible for each change?
Amazingly often, it is useful to ask what
have changed since the last known-good
version, even if you have no collaborators. This often uncovers
unwanted changes, such as forgotten debugging code. I now do this
routinely before checking in a set of changes.
Another issue is
. It's quite common
to get new bug reports for a particular version after the code has
mutated away from it considerably. Sometimes you can recognize
immediately that the bug has already been stomped, but often you
can't. Suppose it doesn't reproduce under the new version. How do you
get back the state of the code for the old version in order to
reproduce and understand it?
To address these problems, you need procedures for keeping a
history of your project, and annotating it with comments that
explain the history. If your project has more than one developer,
you also need mechanisms for making sure developers don't overwrite
each others' versions.