Table of Contents
Part I: The Mechanics of Change
Chapter 1. Changing Software
Four Reasons to Change Software
Improving Design
Risky Change
Chapter 2. Working with Feedback
Software Vise
What Is Unit Testing?
Test Harnesses
Higher-Level Testing
Test Coverings
The Legacy Code Dilemma
Figure 2.2. Invoice update classes with dependencies broken.
The Legacy Code Change Algorithm
Chapter 3. Sensing and Separation
Faking Collaborators
Fake Objects Support Real Tests
The Two Sides of a Fake Object
Chapter 4. The Seam Model
A Huge Sheet of Text
Seams
Seam
Seam Types
Seam
Enabling Point
Link Seams
Usage Tip
Object Seams
Chapter 5. Tools
Automated Refactoring Tools
Tests and Automated Refactoring
Mock Objects
Unit-Testing Harnesses
General Test Harnesses
Part II: Changing Software
Chapter 6. I Don't Have Much Time and I Have to Change It
It Happens Someplace Every Day
Sprout Method
Sprout Class
Wrap Method
Wrap Class
The Decorator Pattern
Summary
Chapter 7. It Takes Forever to Make a Change
Understanding
Lag Time
Breaking Dependencies
The Dependency Inversion Principle
Figure 7.5. Package structure.
Summary
Chapter 8. How Do I Add a Feature?
Test-Driven Development (TDD)
Remove Duplication
TDD and Legacy Code
Programming by Difference
The Liskov Substitution Principle
Figure 8.7. Normalized hierarchy.
Summary
Chapter 9. I Can't Get This Class into a Test Harness
The Case of the Irritating Parameter
Figure 9.1. RGHConnection.
Test Code vs. Production Code
Pass Null
Null Object Pattern
The Case of the Hidden Dependency
The Case of the Construction Blob
The Case of the Irritating Global Dependency
The Case of the Horrible Include Dependencies
The Case of the Onion Parameter
The Case of the Aliased Parameter
Chapter 10. I Can't Run This Method in a Test Harness
The Case of the Hidden Method
Subverting Access Protection
The Case of the "Helpful" Language Feature
The Case of the Undetectable Side Effect
Command/Query Separation
Figure 10.1. AccountDetailFrame.
Chapter 11. I Need to Make a Change. What Methods Should I Test?
Reasoning About Effects
IDE Support for Effect Analysis
Figure 11.1. declarations impacts geTDeclarationCount.
Reasoning Forward
Figure 11.9. Effects through the Element class.
Effect Propagation
Tools for Effect Reasoning
Learning from Effect Analysis
Simplifying Effect Sketches
Effects and Encapsulation
Chapter 12. I Need to Make Many Changes in One Area. Do I Have to Break Dependencies for All the Classes Involved?
Interception Points
Higher-Level Interception Points
Pinch Point
Judging Design with Pinch Points
Using Effect Sketches to Find Hidden Classes
Pinch Point Traps
Chapter 13. I Need to Make a Change, but I Don't Know What Tests to Write
Characterization Tests
The Method Use Rule
Characterizing Classes
When You Find Bugs
Targeted Testing
Refactoring Tool Quirks
A Heuristic for Writing Characterization Tests
Chapter 14. Dependencies on Libraries Are Killing Me
Chapter 15. My Application Is All API Calls
Figure 15.1. A better mailing list server.
Chapter 16. I Don't Understand the Code Well Enough to Change It
Notes/Sketching
Listing Markup
Scratch Refactoring
Delete Unused Code
Chapter 17. My Application Has No Structure
Telling the Story of the System
Naked CRC
Conversation Scrutiny
Chapter 18. My Test Code Is in the Way
Class Naming Conventions
Test Location
Chapter 19. My Project Is Not Object Oriented. How Do I Make Safe Changes?
An Easy Case
A Hard Case
Adding New Behavior
Taking Advantage of Object Orientation
It's All Object Oriented
Chapter 20. This Class Is Too Big and I Don't Want It to Get Any Bigger
Single-Responsibility Principle (SRP)
Figure 20.1. Rule parser.
Seeing Responsibilities
Heuristic #1: Group Methods
Heuristic #2: Look at Hidden Methods
Figure 20.3. RuleParser and TermTokenizer.
Heuristic #3: Look for Decisions That Can Change
Heuristic #4: Look for Internal Relationships
Figure 20.4. Variables in the Reservation class.
Figure 20.6. Feature sketch for Reservation.
Heuristic #5: Look for the Primary Responsibility
Figure 20.11. The ScheduledJob class.
Interface Segregation Principle (ISP)
Figure 20.14. Segregating the interface of ScheduledJob.
Heuristic #6: When All Else Fails, Do Some Scratch Refactoring
Heuristic #7: Focus on the Current Work
Other Techniques
Moving Forward
After Extract Class
Chapter 21. I'm Changing the Same Code All Over the Place
Figure 21.1. AddEmployeeCmd and LoginCommand.
First Steps
Deciding Where to Start
Figure 21.2. Command hierarchy.
Figure 21.3. Pulling up writeField.
Abbreviations
Open/Closed Principle
Chapter 22. I Need to Change a Monster Method and I Can't Write Tests for It
Varieties of Monsters
Tackling Monsters with Automated Refactoring Support
Figure 22.4. Logic class extracted from CommoditySelectionPanel.
The Manual Refactoring Challenge
Strategy
Chapter 23. How Do I Know That I'm Not Breaking Anything?
Hyperaware Editing
Single-Goal Editing
Preserve Signatures
Lean on the Compiler
Chapter 24. We Feel Overwhelmed. It Isn't Going to Get Any Better
Part III: Dependency-Breaking Techniques
Chapter 25. Dependency-Breaking Techniques
Adapt Parameter
Steps
Break Out Method Object
Steps
Definition Completion
Encapsulate Global References
Steps
Expose Static Method
Steps
Extract and Override Call
Extract and Override Factory Method
Steps
Extract and Override Getter
Steps
Extract Implementer
Steps
Extract Interface
Interface Naming
Steps
Extract Interface and Non-Virtual Functions
Introduce Instance Delegator
Introduce Static Setter
The Singleton Design Pattern
Steps
Link Substitution
Parameterize Constructor
Steps
Parameterize Method
Steps
Primitivize Parameter
Steps
Pull Up Feature
Push Down Dependency
Replace Function with Function Pointer
Steps
Replace Global Reference with Getter
Subclass and Override Method
Supersede Instance Variable
Steps
Template Redefinition
Steps
Text Redefinition
Steps
Appendix. Refactoring
Extract Method
Glossary