Key Takeaways
1. Refactoring is Essential for Evolutionary Design
This book is about the marriage of refactoring—the process of improving the design of existing code—with patterns, the classic solutions to recurring design problems.
Continuous Improvement: Refactoring isn't a one-time fix; it's an ongoing process of improving code design. It's about making small, incremental changes to enhance readability, maintainability, and flexibility. This continuous approach allows software to evolve naturally, adapting to changing requirements and avoiding the pitfalls of over-engineering or under-engineering.
Dialogue with Code: Refactoring, especially when combined with test-driven development, transforms programming into a dialogue. You ask questions of the system by writing tests, respond by writing code, and refine your response through refactoring. This iterative process ensures that code is not only functional but also well-designed.
Beyond Expediency: Refactoring is not just about fixing bugs or adding features; it's about making code less annoying to work with. It's about addressing the emotional aspect of programming, making the development experience more pleasant and productive. By continuously improving the design, we make it easier to extend and maintain code, leading to happier programmers and more successful projects.
2. Patterns are Destinations, Refactoring is the Journey
Patterns are where you want to be; refactorings are ways to get there from somewhere else.
Patterns as Targets: Design patterns are not rigid blueprints to be applied upfront; they are targets for refactoring. They represent well-known solutions to recurring design problems, and refactoring provides the means to evolve existing code towards these solutions. This approach allows for a more organic and flexible design process.
Evolutionary Approach: Instead of forcing patterns into a design, refactoring allows them to emerge naturally as the system evolves. This evolutionary approach ensures that patterns are applied only when they are truly needed, avoiding over-engineering and unnecessary complexity. It's about understanding the problem first and then applying the appropriate pattern as a solution.
Gradual Transformation: Refactoring to patterns involves a series of small, low-level transformations that gradually move a design towards a pattern implementation. This gradual approach makes the process safer and more manageable, reducing the risk of introducing defects and allowing for continuous testing and validation. It's about making large changes in tiny steps.
3. Code Smells Indicate Refactoring Needs
When you have learned to look at your words with critical detachment, you will find that rereading a piece five or six times in a row will each time bring to light fresh spots of trouble.
Identifying Design Problems: Code smells are indicators of underlying design problems. They are like warning signs that signal the need for refactoring. Recognizing these smells is crucial for improving code quality and maintainability. Common smells include duplicated code, long methods, conditional complexity, and primitive obsession.
Smells as a Guide: Code smells provide a vocabulary for discussing design problems. They help programmers communicate effectively about areas of code that need improvement. By learning to identify and address these smells, developers can create cleaner, more understandable, and more maintainable code.
Refactoring as a Solution: Each code smell is associated with specific refactorings that can help eliminate the underlying problem. For example, duplicated code can be addressed using Form Template Method, while long methods can be simplified using Compose Method. By understanding the relationship between smells and refactorings, developers can effectively improve their code.
4. Creation Patterns Simplify Object Instantiation
A Creation Method can help make these problems go away.
Creation Methods: Creation Methods provide a more intention-revealing way to instantiate objects than constructors. They allow for more flexibility in naming and can bypass constructor limitations. They also make it easier to find unused creation code. For example, instead of using new Loan()
, you can use Loan.createTermLoan()
.
Factory Pattern: The Factory pattern helps encapsulate object creation logic, reducing coupling and promoting flexibility. It allows for the creation of objects without exposing the concrete classes to the client. This is useful when you want to control how objects are created and ensure that clients interact with them via a common interface.
Builder Pattern: The Builder pattern simplifies the construction of complex objects, especially those with many optional parameters. It provides a step-by-step approach to building objects, making the process more manageable and less error-prone. This is particularly useful for building Composite structures.
5. Simplification Patterns Reduce Complexity
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
Compose Method: Compose Method promotes the creation of small, well-named methods that are easy to understand. It breaks down complex logic into smaller, more manageable chunks, making code more readable and maintainable. This is about writing code that humans can understand, not just computers.
Strategy Pattern: The Strategy pattern helps simplify complex conditional logic by encapsulating different algorithms into separate classes. This allows for the selection of algorithms at runtime, making code more flexible and easier to extend. It's about replacing complex conditionals with polymorphism.
Decorator Pattern: The Decorator pattern allows for the addition of new behavior to objects without modifying their core functionality. It provides a flexible way to add embellishments to objects, making code more modular and easier to maintain. It's about separating core behavior from special-case behavior.
State Pattern: The State pattern simplifies complex state transition logic by encapsulating each state into a separate class. This makes state transitions more explicit and easier to manage, reducing the complexity of conditional logic. It's about replacing complex state-altering conditionals with polymorphism.
Composite Pattern: The Composite pattern simplifies the representation of tree structures by treating individual objects and compositions of objects uniformly. This makes it easier to work with complex hierarchies, reducing the complexity of tree traversal and manipulation. It's about treating one and many objects the same way.
Command Pattern: The Command pattern simplifies conditional dispatchers by encapsulating each action into a separate class. This allows for the dynamic configuration of actions and makes code more flexible and easier to extend. It's about replacing complex switch statements with polymorphism.
6. Generalization Patterns Remove Duplication
Every pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.
Template Method: The Template Method pattern removes duplicated code in subclasses by moving invariant behavior to a superclass. It allows subclasses to customize specific steps of an algorithm while maintaining the overall structure. It's about separating what varies from what is generic.
Extract Composite: Extract Composite removes duplicated Composite implementations in subclasses by moving the common implementation to a superclass. This simplifies subclasses and promotes code reuse. It's about sharing a common Composite implementation.
Replace One/Many Distinctions with Composite: This refactoring removes the need for separate code to handle single objects and collections of objects by using a Composite. It allows for a uniform way to process both single and multiple objects. It's about treating one and many objects the same way.
Observer Pattern: The Observer pattern removes hard-coded notifications by allowing objects to subscribe to changes in other objects. This promotes loose coupling and makes code more flexible and easier to extend. It's about decoupling subjects from their observers.
Adapter Pattern: The Adapter pattern unifies interfaces by providing a common interface for different classes. This reduces duplicated code and makes it easier to work with different classes that perform similar tasks. It's about providing a common interface for different classes.
Extract Adapter: Extract Adapter isolates version-specific code by creating separate adapters for each version of a component, library, or API. This makes code more maintainable and easier to extend. It's about isolating version-specific code.
Interpreter Pattern: The Interpreter pattern replaces implicit languages with explicit ones, making code more flexible and easier to understand. It allows for the dynamic configuration of behavior and reduces the complexity of handling multiple combinations of language elements. It's about making implicit languages explicit.
7. Protection Patterns Enhance Code Safety
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
Replace Type Code with Class: This refactoring enhances type safety by replacing primitive type codes with classes. This prevents invalid assignments and comparisons, making code more robust and less prone to errors. It's about making type codes type-safe.
Limit Instantiation with Singleton: The Singleton pattern limits the number of instances of a class, which can improve performance and reduce memory usage. It's about controlling the number of instances of a class.
Introduce Null Object: The Null Object pattern eliminates null checks by providing a default object that can be used in place of null. This simplifies code and makes it less prone to null pointer exceptions. It's about replacing null checks with a Null Object.
8. Accumulation Patterns Manage Information Gathering
The great thing about software patterns is that they convey many useful design ideas.
Move Accumulation to Collecting Parameter: This refactoring simplifies methods that accumulate information by passing a Collecting Parameter to extracted methods. This makes code more modular and easier to understand. It's about accumulating information in a separate object.
Move Accumulation to Visitor: This refactoring simplifies the accumulation of information from heterogeneous objects by using a Visitor. It allows for the accumulation of data from objects with different interfaces. It's about accumulating information from diverse objects.
Last updated:
Review Summary
Refactoring to Patterns receives mixed reviews, with an average rating of 4.06/5. Readers appreciate its practical approach to merging design patterns with refactoring techniques, providing context for when to apply patterns. Many find it valuable for experienced developers but less useful for beginners. Some praise the real-world examples and step-by-step explanations, while others feel the content is redundant if familiar with both refactoring and design patterns. The book is generally recommended as a solid reference for software developers seeking to improve code quality and design.
Similar Books








Download PDF
Download EPUB
.epub
digital book format is ideal for reading ebooks on phones, tablets, and e-readers.