Working Effec-vely with Legacy Code
Lessons in Prac-ce
The Book
by Michael C. Feathers
published 2004
foreword by “Uncle Bob” Mar-n
influenced by Mar-n Fowler’s Refactoring
What is Legacy Code?
• “difficult to change code that I don’t understand” • “code wriNen a long -me ago” • “code that somebody else wrote”
Refactor Add Feature Fix Bug Op4mize Structure Changes Changes Changes New Behavior Changes Exis-ng Behavior Changes Resource Usage Changes
because SoTware is Never Done
Why do I need to understand the code?
What is Legacy Code?
“Code Without Tests”
Two Methods of SoTware Development
“Edit and Pray” vs.
“Cover and Modify” which brings us to…
The Legacy Code Dilemma
“When we change code, we should have tests in place.”
“To put tests in place,
we oTen have to change code.” (But why?)
Legacy Code Change Algorithm
1. Iden-fy Change Point
2. Find Test Point
3. Break Dependency
4. Write Tests
5. Change and Refactor
Seams
Exchangeable Behavior + an Enabling Point. Seams let you subs7tute one behavior for another by edi-ng only at the enabling point. Seams let you introduce test collaborators.
Object Seams
Most useful type of seam for OOP. Another way of talking about polymorphism.
Code without seam Code with seam
In the Wild
instead of
No Tests == No Up-‐to-‐Date Documenta-on
In the Wild
Duplicate Code
In the Wild
Long, Procedural Methods
def generate_pdf
end
In the Wild
Stateful Programming • Keeping Track of Flags • HTTP Session Abuse
In the Wild
Curse of MVC • Fat Models, Fat Controllers • Overloaded Responsibili-es
So Many Problems
Chapter 6: “I Don’t Have Much Time and I Have to Change It”
Chapter 8: “It Takes Forever to Make a Change”
Chapter 10: “I Can’t Run This Method in a Test”
Chapter 16: “I Don’t Understand the Code Well Enough To Change It”
Chapter 17: “My Applica-on Has No Structure”
Chapter 19: “My Project Is Not Object Oriented. How Do I Make Safe Changes?
Chapter 20: “This Class Is Too Big and I Don’t Want It to Get Any Bigger”
This Class is Too Big
Methods defined on Job:
Single Responsibility Principle
“Every class should have a single responsibility: It should have a single purpose in the system, and there should be only one reason to change it.”
Seeing Responsibili-es
Group Methods
Seeing Responsibili-es
Effect Sketch: Show Internal Rela-onships
Seeing Responsibili-es
Primary Responsibility “Job presents damper inspec-on data in report form.” “Job generates files of reports.” “Job deletes report files.” “Job produces graphs of damper inspec-on data.” “Job persists and retrieves representa-ons of jobs in a database.”
Iden-fy Change Point
We want to refactor Job to extract Reporter.
1. Iden-fy Change Point
2. Find Test Point
3. Break Dependency
4. Write Tests
5. Change and Refactor
Find Test Point Intercep-on Points Higher Level Tes-ng
– don’t have to break dependencies – verifies that your feature actually works – slow, inconvenient – hard to automate – not tes-ng in isola-on
Progressive Strategy
1. Iden-fy Change Point
2. Find Test Point
3. Break Dependency
4. Write Tests
5. Change and Refactor
Break Dependencies
Required for unit tes-ng. Less necessary for higher-‐level tes-ng. We’re gonna skip it (but just this -me).
1. Iden-fy Change Point
2. Find Test Point
3. Break Dependency
4. Write Tests
5. Change and Refactor
Write Tests
“Tes-ng” in the Interac-ve Console:
1. Iden-fy Change Point
2. Find Test Point
3. Break Dependency
4. Write Tests
5. Change and Refactor
Change and Refactor
This was harder than it looks.
1. Iden-fy Change Point
2. Find Test Point
3. Break Dependency
4. Write Tests
5. Change and Refactor
Refactored Code
Five different extracted classes
(plus two more)
Extract Class…Again
BeNer With Seam? We can add a seam by injec-ng the dependency on the reporter.
This way, we can test in isola-on by passing in a FakeReporter.
Unfortunately, this makes our produc-on code ugly:
Seams Everywhere
Legacy Code Ain’t So Bad
• No writer’s block. • Learn as you go. • Easy scapegoat! • Unavoidable, so learn to love it.
Thanks J
Working Effec7vely with Legacy Code
Michael Feathers Amar Shah @amar47shah
because SoTware is Never Done
Refactor to Remove Demeter Viola-on
Top Related