What makes software mature and stable? A mature system lacks no essential features. Users with different habits feel comfortable with the behavior. Stable features interact well under many workflows. In short, the code is robust. Unfortunately, mature code is usually hard to maintain.
Refactoring is the art of making software better without spoiling existing functionality. Rewriting code from scratch does not qualify as refactoring.
Mature code has captured the knowledge of many participants -- programmers, testers, and customers -- over years of use. Most design decisions are described only in the code itself.
Much of the cost of stabilizing software is ensuring that all features play well together. If you double the number of features, you can quadruple the cost of stabilization.
A total rewrite requires discarding countless small decisions captured in the original code. You are likely to repeat many struggles with design. Some of your choices will improve, but you may also underestimate the inspiration and serendipity of the previous work. The code must again pass through many hands to regain robustness.
On the other hand, no one likes looking at old code. Most programmers dislike their own creations after less than a year. Any shipped product is already old enough to contain many unsightly messes. Obsolete patterns and inconsistent styles make old code hard to understand and modify.
Refactoring simplifies existing code and makes room for new functionality, without sacrificing functionality that users already take for granted. Refactoring should add robustness, not reconstruct it.
Small changes allow you to adjust your plans as you discover unforeseen implications. You make one small perturbation to the code at a time and retest to catch hidden interactions. Large changes are more likely to lead to prolonged testing and patching. A rewrite is the largest possible change.
Refactoring requires new tests to protect existing functionality. New tests help you define and discover the behavior of existing code. Tests give you the courage to make modifications.
Translating existing code into a new language is the least justifiable form of rewriting. Instead find ways to make different languages work together. Or rewrite small modules as needed for enhancements.
For many first-rate examples, see "Refactoring" by Martin Fowler from Addison Wesley. http://www.refactoring.com/ He demonstrates many ways to break large design changes into small testable steps, with much more flexibility in the final design.
Bill Harlan -- 2002
Return to parent directory.