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”
Why do I need to understand the code? because SoTware is Never Done Refactor Add Feature Fix Bug Op4mize Structure Changes Changes Changes New Behavior Changes Exis-ng Behavior Changes Resource Usage Changes
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 No Tests == No Up-­‐to-­‐Date Documenta-on instead of
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

Working Effectively with Legacy Code: Lessons in Practice

  • 1.
    Working Effec-vely with Legacy Code Lessons in Prac-ce
  • 2.
    The Book by Michael C. Feathers published 2004 foreword by “Uncle Bob” Mar-n influenced by Mar-n Fowler’s Refactoring
  • 3.
    What is Legacy Code? • “difficult to change code that I don’t understand” • “code wriNen a long -me ago” • “code that somebody else wrote”
  • 4.
    Why do I need to understand the code? because SoTware is Never Done Refactor Add Feature Fix Bug Op4mize Structure Changes Changes Changes New Behavior Changes Exis-ng Behavior Changes Resource Usage Changes
  • 5.
    What is Legacy Code? “Code Without Tests”
  • 6.
    Two Methods of SoTware Development “Edit and Pray” vs. “Cover and Modify” which brings us to…
  • 7.
    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?)
  • 8.
    Legacy Code Change Algorithm 1. Iden-fy Change Point 2. Find Test Point 3. Break Dependency 4. Write Tests 5. Change and Refactor
  • 9.
    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.
  • 10.
    Object Seams Most useful type of seam for OOP. Another way of talking about polymorphism. Code without seam Code with seam
  • 11.
    In the Wild No Tests == No Up-­‐to-­‐Date Documenta-on instead of
  • 12.
    In the Wild Duplicate Code
  • 13.
    In the Wild Long, Procedural Methods def generate_pdf end
  • 14.
    In the Wild Stateful Programming • Keeping Track of Flags • HTTP Session Abuse
  • 15.
    In the Wild Curse of MVC • Fat Models, Fat Controllers • Overloaded Responsibili-es
  • 16.
    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”
  • 17.
    This Class is Too Big Methods defined on Job:
  • 18.
    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.”
  • 19.
  • 20.
    Seeing Responsibili-es Effect Sketch: Show Internal Rela-onships
  • 21.
    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.”
  • 22.
    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
  • 23.
    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
  • 24.
    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
  • 25.
    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
  • 26.
    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
  • 27.
    Refactored Code Five different extracted classes (plus two more)
  • 28.
  • 29.
    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:
  • 30.
  • 31.
    Legacy Code Ain’t So Bad • No writer’s block. • Learn as you go. • Easy scapegoat! • Unavoidable, so learn to love it.
  • 32.
    Thanks J Working Effec7vely with Legacy Code Michael Feathers Amar Shah @amar47shah
  • 33.
    because SoTware is Never Done Refactor to Remove Demeter Viola-on