Searching...
English
EnglishEnglish
EspañolSpanish
简体中文Chinese
FrançaisFrench
DeutschGerman
日本語Japanese
PortuguêsPortuguese
ItalianoItalian
한국어Korean
РусскийRussian
NederlandsDutch
العربيةArabic
PolskiPolish
हिन्दीHindi
Tiếng ViệtVietnamese
SvenskaSwedish
ΕλληνικάGreek
TürkçeTurkish
ไทยThai
ČeštinaCzech
RomânăRomanian
MagyarHungarian
УкраїнськаUkrainian
Bahasa IndonesiaIndonesian
DanskDanish
SuomiFinnish
БългарскиBulgarian
עבריתHebrew
NorskNorwegian
HrvatskiCroatian
CatalàCatalan
SlovenčinaSlovak
LietuviųLithuanian
SlovenščinaSlovenian
СрпскиSerbian
EestiEstonian
LatviešuLatvian
فارسیPersian
മലയാളംMalayalam
தமிழ்Tamil
اردوUrdu
Refactoring to Patterns

Refactoring to Patterns

by Joshua Kerievsky 2004 367 pages
4.05
1k+ ratings
Listen
Try Full Access for 7 Days
Unlock listening & more!
Continue

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:

FAQ

What is Refactoring to Patterns by Joshua Kerievsky about?

  • Combines refactoring and patterns: The book explores how to improve existing codebases by incrementally applying design patterns through safe, behavior-preserving refactorings.
  • Focus on evolutionary design: It emphasizes evolving software designs over time, rather than relying solely on up-front architecture.
  • Practical catalog and examples: Readers are provided with a catalog of 27 pattern-directed refactorings, real-world code examples, and guidance on recognizing design smells.
  • Bridges two disciplines: The book unites the worlds of refactoring and design patterns, showing how they can work together to create cleaner, more maintainable code.

Why should I read Refactoring to Patterns by Joshua Kerievsky?

  • Bridges theory and practice: The book fills a gap by showing how to introduce design patterns incrementally, avoiding both over-engineering and under-engineering.
  • Step-by-step guidance: It offers detailed, accessible refactoring steps with real-world examples, making it suitable even for those with limited experience in patterns or refactoring.
  • Improves code quality: By learning pattern-directed refactorings, readers can reduce duplication, clarify intent, and make codebases more maintainable.
  • Essential for legacy code: The techniques are especially valuable for improving legacy systems or evolving complex codebases without breaking existing behavior.

What are the main goals and key takeaways from Refactoring to Patterns by Joshua Kerievsky?

  • Synergy of patterns and refactoring: Learn how to combine refactoring techniques with design patterns to improve codebases effectively and safely.
  • Recognize and address design smells: The book teaches how to identify 12 common code smells that signal the need for pattern-directed refactorings.
  • Safe, incremental improvement: Emphasizes using sequences of low-level refactorings to evolve designs, ensuring behavior is preserved at every step.
  • Multiple paths to patterns: Demonstrates that there are often several ways to implement or approach a pattern, encouraging thoughtful, context-driven design decisions.

What background knowledge is recommended for reading Refactoring to Patterns by Joshua Kerievsky?

  • Object-oriented programming basics: Familiarity with concepts like inheritance, polymorphism, encapsulation, and interfaces is assumed.
  • Refactoring fundamentals: Understanding basic refactorings (e.g., Extract Method, Move Method) is helpful; having Martin Fowler’s Refactoring book as a reference is suggested.
  • Design patterns awareness: Some knowledge of classic design patterns (from the GoF book) is useful, but not required, as the book provides summaries and UML diagrams.
  • Test-driven development familiarity: While not mandatory, understanding TDD concepts will help in applying the book’s advice on safe, incremental changes.

How does Refactoring to Patterns by Joshua Kerievsky define and use "pattern-directed refactorings"?

  • Definition: Pattern-directed refactorings are sequences of low-level, behavior-preserving changes that move code toward, to, or away from a design pattern.
  • Purpose: They provide a guided, incremental path for evolving code, helping avoid premature or unnecessary pattern implementations.
  • Structure: Each refactoring includes motivation, step-by-step mechanics, real-world examples, and a discussion of benefits and liabilities.
  • Empowers developers: This approach enables programmers to confidently apply patterns in a way that fits their code’s current needs and context.

What are the most important design smells discussed in Refactoring to Patterns by Joshua Kerievsky, and how do they relate to patterns?

  • Twelve key smells: Examples include Duplicated Code, Long Method, Conditional Complexity, Primitive Obsession, Indecent Exposure, Solution Sprawl, and Large Class.
  • Smells as refactoring signals: Each smell indicates a specific area where pattern-directed refactorings can improve the design.
  • Patterns as solutions: The book maps common smells to appropriate patterns, such as using Template Method to remove duplication or Strategy to simplify conditionals.
  • Guides code evolution: Recognizing these smells helps developers decide when and how to refactor toward patterns for cleaner, more maintainable code.

How does Refactoring to Patterns by Joshua Kerievsky explain the relationship between refactoring and design patterns?

  • Patterns as design targets: Patterns represent desirable structures, while refactorings are the means to evolve code toward those structures.
  • Evolutionary, not revolutionary: The book advocates for small, safe steps rather than big, up-front pattern implementations.
  • Synergy and balance: Understanding when and why to refactor to, towards, or away from patterns helps avoid both over-engineering and under-engineering.
  • Patterns as flexible goals: The approach encourages using patterns as guides, not rigid templates, adapting them to the code’s evolving needs.

What is the difference between refactoring to, towards, and away from patterns in Refactoring to Patterns by Joshua Kerievsky?

  • Refactoring to a pattern: Fully implements a design pattern to achieve a clear design improvement, such as applying the Template Method.
  • Refactoring towards a pattern: Makes partial improvements that move the design closer to a pattern, stopping if sufficient clarity or simplicity is achieved.
  • Refactoring away from a pattern: Removes or simplifies a pattern when it adds unnecessary complexity, such as inlining a Singleton.
  • Context-driven decisions: The book emphasizes choosing the right direction based on the code’s current needs and future evolution.

How does Refactoring to Patterns by Joshua Kerievsky recommend using test-driven development (TDD) and continuous refactoring?

  • TDD as a safety net: Write a failing test, make it pass, then refactor—repeating this cycle to ensure safe, incremental improvements.
  • Supports safe refactoring: Automated tests provide confidence that behavior is preserved during each refactoring step.
  • Composite and test-driven refactorings: The book distinguishes between composite refactorings (sequences of small steps) and test-driven refactorings (reimplementing code guided by tests).
  • Enables evolutionary design: This approach allows for continuous, low-risk evolution of codebases.

What are some key pattern-directed refactorings covered in Refactoring to Patterns by Joshua Kerievsky?

  • Creation patterns: Includes Replace Constructors with Creation Methods, Move Creation Knowledge to Factory, and Introduce Polymorphic Creation with Factory Method.
  • Simplification patterns: Covers Compose Method, Replace Conditional Logic with Strategy, and Move Embellishment to Decorator.
  • Generalization and protection: Features Form Template Method, Extract Composite, Replace State-Altering Conditionals with State, Introduce Null Object, and Inline Singleton.
  • Accumulation and utilities: Discusses Move Accumulation to Collecting Parameter, Move Accumulation to Visitor, Chain Constructors, and Unify Interfaces.

How does Refactoring to Patterns by Joshua Kerievsky detail the process of refactoring to the Decorator pattern?

  • Stepwise transformation: The book walks through refactoring a class (e.g., StringNode) to use Decorator, starting by identifying an interface and moving embellishment logic into decorator classes.
  • From inheritance to delegation: It demonstrates breaking inheritance in favor of delegation, creating delegate fields and forwarding methods to enable flexible decoration.
  • Parameter extraction: The process includes extracting parameters to pass decorated instances and ensuring the decorator fully implements the interface.
  • Avoids recursion pitfalls: Special attention is given to handling infinite recursion and ensuring the decorator pattern is implemented transparently.

What is the motivation and benefit of replacing state-altering conditionals with the State pattern in Refactoring to Patterns by Joshua Kerievsky?

  • Simplifies complex state logic: The main motivation is to tame sprawling conditional logic that controls state transitions, which can be hard to maintain.
  • Encapsulates state behavior: The State pattern moves state-specific behavior and transitions into separate classes, clarifying the design.
  • Improves extensibility: This approach makes it easier to add new states or transitions without modifying existing code.
  • Reduces conditional clutter: By removing or reducing state-changing conditionals, the code becomes simpler and more maintainable.

What is the overall philosophy and advice in the Afterword of Refactoring to Patterns by Joshua Kerievsky?

  • Refactoring as design algebra: The book likens refactoring to algebra and design patterns to word problems, emphasizing the importance of understanding the thought process behind transformations.
  • Focus on understanding: The true value lies in grasping the underlying patterns and insights, not just memorizing specific refactorings.
  • Primer, not a cookbook: Readers are encouraged to study the examples to internalize the approach, rather than treating the book as a set of recipes.
  • Empowers creative problem-solving: This mindset enables developers to apply principles flexibly and effectively to a wide range of design challenges.

Review Summary

4.05 out of 5
Average of 1k+ ratings from Goodreads and Amazon.

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.

Your rating:
4.47
27 ratings

About the Author

Joshua Kerievsky is a software developer and author known for his expertise in agile development practices and design patterns. He is the founder and CEO of Industrial Logic, a company that provides training and consulting services in software development. Kerievsky is recognized for his contributions to the field of software engineering, particularly in the areas of refactoring and design patterns. He has written extensively on these topics and is a frequent speaker at industry conferences. His work focuses on helping developers improve their skills and create more maintainable, efficient code through the application of proven design principles and refactoring techniques.

Download PDF

To save this Refactoring to Patterns summary for later, download the free PDF. You can print it out, or read offline at your convenience.
Download PDF
File size: 0.20 MB     Pages: 12

Download EPUB

To read this Refactoring to Patterns summary on your e-reader device or app, download the free EPUB. The .epub digital book format is ideal for reading ebooks on phones, tablets, and e-readers.
Download EPUB
File size: 2.94 MB     Pages: 11
Listen to Summary
0:00
-0:00
1x
Dan
Andrew
Michelle
Lauren
Select Speed
1.0×
+
200 words per minute
Home
Library
Get App
Create a free account to unlock:
Requests: Request new book summaries
Bookmarks: Save your favorite books
History: Revisit books later
Recommendations: Personalized for you
Ratings: Rate books & see your ratings
100,000+ readers
Try Full Access for 7 Days
Listen, bookmark, and more
Compare Features Free Pro
📖 Read Summaries
All summaries are free to read in 40 languages
🎧 Listen to Summaries
Listen to unlimited summaries in 40 languages
❤️ Unlimited Bookmarks
Free users are limited to 4
📜 Unlimited History
Free users are limited to 4
📥 Unlimited Downloads
Free users are limited to 1
Risk-Free Timeline
Today: Get Instant Access
Listen to full summaries of 73,530 books. That's 12,000+ hours of audio!
Day 4: Trial Reminder
We'll send you a notification that your trial is ending soon.
Day 7: Your subscription begins
You'll be charged on May 23,
cancel anytime before.
Consume 2.8x More Books
2.8x more books Listening Reading
Our users love us
100,000+ readers
"...I can 10x the number of books I can read..."
"...exceptionally accurate, engaging, and beautifully presented..."
"...better than any amazon review when I'm making a book-buying decision..."
Save 62%
Yearly
$119.88 $44.99/year
$3.75/mo
Monthly
$9.99/mo
Try Free & Unlock
7 days free, then $44.99/year. Cancel anytime.
Scanner
Find a barcode to scan

Settings
General
Widget
Loading...