Facebook Pixel
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

Refactoring

Improving the Design of Existing Code
by Martin Fowler 1999 431 pages
4.24
8k+ ratings
Listen

Key Takeaways

1. Refactoring: Controlled Code Improvement

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.

Definition and Purpose. Refactoring is not about adding new features or fixing bugs; it's about improving the internal design of existing code without changing its external behavior. It's a disciplined approach to cleaning up code, making it easier to understand, modify, and maintain. The goal is to prevent software decay and ensure that the code remains robust and adaptable over time.

Two Hats Metaphor. When refactoring, you should wear two distinct hats: one for adding functionality and another for refactoring. When adding functionality, you focus on new features and tests. When refactoring, you focus on restructuring the code without adding new features or tests. This separation of concerns helps maintain focus and prevents the introduction of bugs.

Continuous Process. Refactoring is not a one-time event but an ongoing process that should be integrated into the development cycle. It's a continuous effort to improve the design of the code as you work on it, rather than a separate activity done periodically. This approach ensures that the code remains clean and maintainable throughout its lifecycle.

2. Code Smells: Identifying Refactoring Needs

If it stinks, change it.

Indicators of Poor Code. Code smells are indicators of potential problems in the code that suggest the need for refactoring. These are not necessarily bugs, but they are signs of poor design that can lead to future problems. Common code smells include:

  • Duplicated Code: Identical or similar code in multiple places
  • Long Method: Methods that are too long and complex
  • Large Class: Classes that have too many responsibilities
  • Long Parameter List: Methods with too many parameters
  • Divergent Change: Classes that are changed for different reasons
  • Shotgun Surgery: Changes that require modifications in many classes
  • Feature Envy: Methods that are more interested in another class's data
  • Data Clumps: Groups of data that appear together in multiple places
  • Primitive Obsession: Overuse of primitive data types instead of objects
  • Switch Statements: Conditional logic based on type codes
  • Parallel Inheritance Hierarchies: Subclasses that mirror each other
  • Lazy Class: Classes that don't do enough to justify their existence
  • Speculative Generality: Unnecessary complexity for future needs
  • Temporary Field: Fields that are used only in certain circumstances
  • Message Chains: Long sequences of method calls
  • Middle Man: Classes that delegate most of their work
  • Inappropriate Intimacy: Classes that are too coupled
  • Alternative Classes with Different Interfaces: Classes that do the same thing with different interfaces
  • Incomplete Library Class: Library classes that lack needed functionality
  • Data Class: Classes that only hold data
  • Refused Bequest: Subclasses that don't use inherited methods
  • Comments: Excessive comments that indicate unclear code

Subjective but Useful. Code smells are subjective, but they provide a practical way to identify areas of code that need attention. They are not precise rules but rather guidelines that help you focus on areas that may benefit from refactoring.

Actionable Insights. Code smells are not just about identifying problems; they also suggest specific refactorings that can be used to address those problems. By recognizing the smells, you can choose the appropriate refactoring techniques to improve the code.

3. Testing: The Bedrock of Safe Refactoring

Before you start refactoring, check that you have a solid suite of tests. These tests must be self-checking.

Essential for Refactoring. Tests are crucial for refactoring because they provide a safety net that allows you to make changes with confidence. Without tests, you risk introducing bugs and breaking existing functionality. Tests should be self-checking, meaning they automatically verify the results and report any failures.

Self-Checking Tests. Self-checking tests are essential for efficient refactoring. They eliminate the need for manual verification, allowing you to run tests frequently and quickly. This rapid feedback loop is crucial for identifying and fixing bugs early in the refactoring process.

Test-Driven Development. Writing tests before you write code is a powerful technique that can improve the design and quality of your software. By writing tests first, you clarify your requirements and ensure that your code meets those requirements. This approach also makes refactoring easier because you have a solid set of tests to rely on.

4. Method Composition: Breaking Down Complexity

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Small Methods are Key. Short, well-named methods are easier to understand, reuse, and modify. They also make it easier to see the overall structure of the code. Long methods, on the other hand, are difficult to understand and maintain.

Extract Method. The most common refactoring for method composition is Extract Method, which involves breaking down a long method into smaller, more manageable pieces. This technique improves readability and makes it easier to move code around.

Other Composition Techniques. Other refactorings for method composition include:

  • Inline Method: Replacing a method call with its body
  • Replace Temp with Query: Replacing temporary variables with method calls
  • Split Temporary Variable: Splitting a temporary variable into multiple variables
  • Remove Assignments to Parameters: Avoiding assignments to parameters
  • Replace Method with Method Object: Turning a method into an object
  • Substitute Algorithm: Replacing an algorithm with a clearer one

By using these techniques, you can create methods that are easier to understand, reuse, and modify, leading to more maintainable and robust code.

5. Feature Movement: Placing Responsibilities Correctly

In most cases a method should be on the object whose data it uses.

Object-Oriented Principles. Object-oriented programming is about packaging data with the behavior that operates on that data. Methods should be placed on the object that owns the data they use. This principle helps to create a more cohesive and understandable design.

Move Method. The Move Method refactoring involves moving a method from one class to another. This is often done when a method is more interested in the data of another class than the class it is currently in.

Move Field. The Move Field refactoring involves moving a field from one class to another. This is often done when a field is more closely related to the behavior of another class.

Other Feature Movement Techniques. Other refactorings for feature movement include:

  • Extract Class: Creating a new class to encapsulate a subset of responsibilities
  • Inline Class: Merging a class into another class
  • Hide Delegate: Hiding the details of a delegate object
  • Remove Middle Man: Removing unnecessary delegation
  • Introduce Foreign Method: Adding a method to a class you can't modify
  • Introduce Local Extension: Creating a new class to extend a class you can't modify

By using these techniques, you can ensure that methods and data are placed on the objects that are most appropriate for them, leading to a more cohesive and understandable design.

6. Data Organization: Structuring for Clarity

Good code should communicate what it is doing clearly, and variable names are a key to clear code.

Data as Objects. Data should be treated as objects, not just primitive types. This means encapsulating data with behavior and creating objects that represent meaningful concepts.

Refactorings for Data Organization:

  • Self Encapsulate Field: Accessing fields through accessors
  • Replace Data Value with Object: Turning a data value into an object
  • Change Value to Reference: Turning a value object into a reference object
  • Change Reference to Value: Turning a reference object into a value object
  • Replace Array with Object: Replacing an array with an object
  • Duplicate Observed Data: Duplicating data to keep it in sync
  • Change Unidirectional Association to Bidirectional: Adding a back pointer
  • Change Bidirectional Association to Unidirectional: Removing a back pointer
  • Replace Magic Number with Symbolic Constant: Replacing magic numbers with constants
  • Encapsulate Field: Making a field private and providing accessors
  • Encapsulate Collection: Returning a read-only view of a collection
  • Replace Record with Data Class: Turning a record into a data class
  • Replace Type Code with Class: Replacing a type code with a class
  • Replace Type Code with Subclasses: Replacing a type code with subclasses
  • Replace Type Code with State/Strategy: Replacing a type code with a state object

By using these techniques, you can create data structures that are more meaningful, easier to understand, and more robust to change.

7. Conditional Simplification: Making Logic Transparent

When you find you have to add a feature to a program, and the program's code is not structured in a convenient way to add the feature, first refactor the program to make it easy to add the feature, then add the feature.

Clear Conditional Logic. Conditional logic can quickly become complex and difficult to understand. It's important to simplify conditional expressions to make them more readable and maintainable.

Refactorings for Conditional Simplification:

  • Decompose Conditional: Breaking down a conditional into smaller methods
  • Consolidate Conditional Expression: Combining multiple conditions into one
  • Consolidate Duplicate Conditional Fragments: Removing duplicate code in conditional branches
  • Remove Control Flag: Replacing control flags with break or return statements
  • Replace Nested Conditional with Guard Clauses: Using guard clauses for special cases
  • Replace Conditional with Polymorphism: Using polymorphism to handle conditional behavior
  • Introduce Null Object: Replacing null checks with a null object
  • Introduce Assertion: Making assumptions explicit with assertions

By using these techniques, you can create conditional logic that is easier to understand, modify, and maintain, leading to more robust and reliable code.

8. Interface Refinement: Streamlining Interactions

The key here is not method length but the semantic distance between what the method does and how it does it.

Clear and Concise Interfaces. Interfaces should be clear, concise, and easy to use. They should communicate the purpose of the methods and make it easy for clients to interact with the object.

Refactorings for Interface Refinement:

  • Rename Method: Changing the name of a method to better reflect its purpose
  • Add Parameter: Adding a parameter to a method
  • Remove Parameter: Removing a parameter from a method
  • Separate Query from Modifier: Separating methods that return a value from those that change state
  • Parameterize Method: Combining similar methods into one with a parameter
  • Replace Parameter with Explicit Methods: Creating separate methods for each parameter value
  • Preserve Whole Object: Passing the whole object instead of individual values
  • Replace Parameter with Method: Replacing a parameter with a method call
  • Introduce Parameter Object: Replacing multiple parameters with an object
  • Remove Setting Method: Removing a setting method for a field
  • Hide Method: Making a method private
  • Replace Constructor with Factory Method: Replacing a constructor with a factory method
  • Encapsulate Downcast: Moving downcasts to within the method
  • Replace Error Code with Exception: Replacing error codes with exceptions
  • Replace Exception with Test: Replacing exceptions with conditional tests

By using these techniques, you can create interfaces that are easier to understand, use, and maintain, leading to more flexible and robust code.

9. Generalization: Leveraging Inheritance Effectively

Design Patterns provide targets for your refactorings.

Effective Use of Inheritance. Inheritance is a powerful tool for code reuse and polymorphism, but it should be used carefully. It's important to ensure that subclasses are truly subtypes of their superclasses and that they inherit only the behavior that is relevant to them.

Refactorings for Generalization:

  • Pull Up Field: Moving a field to the superclass
  • Pull Up Method: Moving a method to the superclass
  • Pull Up Constructor Body: Moving constructor logic to the superclass
  • Push Down Method: Moving a method to the subclass
  • Push Down Field: Moving a field to the subclass
  • Form Template Method: Creating a template method in the superclass
  • Extract Subclass: Creating a new subclass
  • Extract Superclass: Creating a new superclass
  • Extract Interface: Creating a new interface
  • Collapse Hierarchy: Merging a superclass and subclass
  • Replace Inheritance with Delegation: Replacing inheritance with delegation
  • Replace Delegation with Inheritance: Replacing delegation with inheritance

By using these techniques, you can create inheritance hierarchies that are more flexible, maintainable, and easier to understand.

10. Big Refactorings: Transforming Entire Systems

The most important lesson from this example is the rhythm of refactoring: test, small change, test, small change, test, small change. It is that rhythm that allows refactoring to move quickly and safely.

Large-Scale Changes. Big refactorings are large-scale changes that can transform entire systems. They often involve multiple refactorings and require a significant amount of time and effort.

Examples of Big Refactorings:

  • Tease Apart Inheritance: Separating tangled inheritance hierarchies
  • Convert Procedural Design to Objects: Turning procedural code into object-oriented code
  • Separate Domain from Presentation: Separating business logic from user interface code
  • Extract Hierarchy: Simplifying a complex class by creating a hierarchy

Incremental Approach. Big refactorings should be done incrementally, one step at a time. This approach allows you to make progress without breaking the system and to adapt to new insights as you go.

Team Collaboration. Big refactorings often require collaboration among the entire development team. It's important to communicate the goals of the refactoring and to ensure that everyone is on the same page.

By using these techniques, you can transform entire systems, making them more flexible, maintainable, and easier to evolve.

Last updated:

Review Summary

4.24 out of 5
Average of 8k+ ratings from Goodreads and Amazon.

Refactoring is highly regarded as an essential read for software developers, offering practical techniques to improve code quality. Readers appreciate its clear explanations, JavaScript examples, and catalog of refactorings. Many find it useful as a reference guide throughout their careers. Some criticize outdated content in older editions and paper quality issues. While experienced developers may find less new information, most agree it's valuable for understanding and applying refactoring principles. The book emphasizes incremental changes, controlled processes, and adapting refactoring techniques to specific contexts.

About the Author

Martin Fowler is a renowned software engineer and thought leader in the field of enterprise software design. Born in 1963, he has made significant contributions to agile software development methodologies, including extreme programming. As Chief Scientist at ThoughtWorks, Fowler advocates for best practices in software development and has authored influential books on refactoring, domain-driven design, and enterprise application architecture. His work has shaped modern approaches to software design, emphasizing clean code, continuous integration, and adaptive planning. Fowler's ideas and writings continue to influence developers and organizations worldwide, promoting more efficient and effective software development processes.

Download PDF

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

Download EPUB

To read this Refactoring 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.95 MB     Pages: 14
0:00
-0:00
1x
Dan
Andrew
Michelle
Lauren
Select Speed
1.0×
+
200 words per minute
Create a free account to unlock:
Requests: Request new book summaries
Bookmarks: Save your favorite books
History: Revisit books later
Ratings: Rate books & see your ratings
Unlock Unlimited Listening
🎧 Listen while you drive, walk, run errands, or do other activities
2.8x more books Listening Reading
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 Jan 25,
cancel anytime before.
Compare Features Free Pro
Read full text summaries
Summaries are free to read for everyone
Listen to summaries
12,000+ hours of audio
Unlimited Bookmarks
Free users are limited to 10
Unlimited History
Free users are limited to 10
What our users say
30,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.
Settings
Appearance
Black Friday Sale 🎉
$20 off Lifetime Access
$79.99 $59.99
Upgrade Now →