Monday, January 8, 2007

Refactoring: Improving the Design of Existing Code

Refactoring is essential reading for anyone involved in the construction of software using object oriented languages. Fowler and his fellow contributors do an incredible job of simultaneously introducing and formalizing a code improvement technique called "refactoring."

To quote Fowler from the Preface, "Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. In essence when you refactor you are improving the design of the code after it has been written."

This is a powerful concept since it free us as developers from the pressure of getting every absolute detail right the first time. When building any system, object oriented or not, even the best developer is not going to be able to capture every nuance and contingency in her code the first time. Designing systems and writing code is a constant process of making trade-offs. Hopefully we do our best and make all the right decisions the first time we design the system and write the code. Three things, though, prevent that from happening: one, we are not perfect; two, we don't always have all the necessary information required to make the "right" design decisions; and three, requirements change and new functionality needs to be added. Refactoring gives us a way to adjust the design without breaking the code.

After introducing the concept of refactoring, and delving into the details of the technique, the book walks through 72 "refactorings." This catalog idea is very similar to the catalog of design patterns that appears in the book Design Patterns by Erich Gamma, et al. Each refactoring has a name such as "Move Method" or "Replace Conditional with Polymorphism," and contains a detailed explanation of a design problem and solution. Performing a refactoring means making small, incremental changes to code, and retesting each step of the way so that the changes can be made with the least disruption possible. That may sound tedious, but it's actually quite straightforward and interesting to read. The book wraps up with a few chapters written by the contributing authors. These chapters tie together the material that makes up the bulk of the book, further grounding the techniques in the real world we all write code in.

I call this book "essential reading" for three reasons: first, the author's humble, almost self-deprecating, writing style sends exactly the right message to the reader: we are not perfect, and there is no need for us to be; software design and construction are not perfect processes, and there is no need for them to be. This is a message we all need to hear. Second, the book offers concrete guidance on performing the refactorings, with clear explanations, justifications, caveats, and examples. The catalog of refactorings will be the most lasting contribution of the book, and is what will keep you coming back to the book often. Third, reading through the catalog of refactorings is a suprisingly excellent primer/refresher on techniques to adopt and pitfalls to avoid when designing and building object oriented software. In this respect, it shares qualities with Steve McConnell's Code Complete and also Gamma et al's Design Patterns. Refactoring makes a perfect companion volume to these essential books.

Finally, as both a fellow writer and a reader, I'd like to commend the authors of Refactoring for bringing this important subject matter to us with a clear, conversational, decidedly non-academic style. More of this kind of writing is needed if the important ideas of software engineering are to be delivered to the majority of software developers, who have little interest in academia and its often dry, cumbersome, and wordy writing style--which serves its purpose in the world of research and academia, but which can try the patience of pratitioners.