Refactoring and Patterns
On various projects, I've observed what and how my colleagues and I refactor. While we use many of the refactorings described in Refactoring [F], we also find places where patterns help us improve our designs. At such times, we refactor to or towards patterns, being careful not to produce overly flexible or unnecessarily sophisticated solutions.
When I explored the motivations for applying pattern-directed refactorings, I found they are identical to the general motivations for implementing low-level refactorings: to reduce or remove duplication, to simplify what is complicated, and to make code better at communicating its intention.
This motivation can easily be missed if you study only a portion of a design pattern. For example, every pattern in Design Patterns [DP] includes a section known as the Intent. The authors of Design Patterns describe the Intent as follows: "A short statement that answers the following questions: What does the design pattern do? What is its rationale and intent? What particular design issues or problem does it address?" [DP, 6]. Despite this description, the Intent sections for many design patterns only hint at the main problem the pattern solves. Instead, more of the focus is put on what the pattern does. Here are two examples.
Intent of Template Method
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure. [DP, 325]
Intent of State
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. [DP, 315]
These Intent descriptions don't say that a Template Method helps reduce or remove duplicated code in similar methods of subclasses in a hierarchy or that the State pattern helps simplify complex conditional state-changing logic. If programmers study all of the sections of a design pattern, particularly the Applicability section, they'll learn about the problems the pattern addresses.
However, when using the Design Patterns book during design, many programmers, myself included, have read the Intent section of a pattern to see whether the pattern could provide a good fit for a given situation. This method of choosing a pattern doesn't work as well as a method that helps you match a design problem to the problems addressed by a pattern. Why? Because patterns exist to solve problems, and learning whether they really can help in a given situation involves understanding what problems they help solve.
The refactoring literature tends to focus more on specific design problems than the patterns literature does. If you study the first page of a refactoring, you'll see the kind of problem the refactoring helps solve. The catalog of pattern-directed refactorings presented in this book, which is a direct continuation of work started in Refactoring, is intended to help you see what kinds of specific problems the patterns help solve.
While this book bridges the gap between patterns and refactoring, the connection between the two was noted by the authors of Design Patterns in the conclusion to their great book:
Our design patterns capture many of the structures that result from refactoring. . . . Design patterns thus provide targets for your refactorings. [DP, 354]
Martin Fowler makes a similar observation near the beginning of Refactoring:
There is a natural relation between patterns and refactorings. Patterns are where you want to be; refactorings are ways to get there from somewhere else. [F, 107]