SlideShare a Scribd company logo
Working Effectively with Legacy Code  written by Michael Feathers Something I understand about the book
Contents The Book Definition of Legacy Code Problems of the Conservative Approach The Automatic Test Approach Example of Characterization Test Breaking Dependencies (not yet ready) Seams (not yet ready) Conclusion: the complaints/solutions matrix
The Book Robert C. Martin Series Michael C. Feathers http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052   Paperback:  456 pages Publisher:  Prentice Hall PTR; 1 edition (October 2, 2004)
What is legacy code? (for me/us?) Code that: is difficult to understand is fragile is difficult to modify is not (or not well) documented has been inherited from others But that : is still useful!
What is legacy code? (M.Feathers) M.Feathers says: Legacy Code  ≡ Code without automatic tests Why?
The conservative approach No automatic tests  leads to   Manual testing  that   leads to   High risk of introduce bugs  that leads to   Fear of change  so You prefer add more mess instead  cleaning up  the existing code and   the code get worse,  the cost/time of adding features increases If it ain't broke don't fix it
Preserving Behaviour with Characterization Tests  Write tests for an existings program Write a test that “Describe” the  actual  behaviour Use these test as regression tests during the refactoring/feature addition. Please note that: “actual” is not always the same as “correct”.
Characterization Tests Example (1/5) public static int[] slaDjcl(double djm) { long ld, jd, n4, nd10; if ((djm <= -2395520.0) || (djm >= 1e9)) { throw new IllegalArgumentException(&quot;MJD out of valid range&quot;); } ld = (long) djm; jd = ld + 2400001L; n4 = 4L * (jd + ((6L * ((4L * jd - 17918L) / 146097L)) / 4L + 1L) / 2L - 37L); nd10 = 10L * (((n4 - 237L) % 1461L) / 4L) + 5L; int[] ret = new int[3]; ret[0] = (int) (n4 / 1461L - 4712L); ret[1] = (int) (((nd10 / 306L + 2L) % 12L) + 1L); ret[2] = (int) ((nd10 % 306L) / 10L + 1L); return ret; }
Characterization  Tests Example (2/5) @Test public void testSlaDjcl() { assertArrayEquals(new int[]{},slaDjcl(0.0)); } Testcase: testSlaDjcl(prova.ProvaTest):  FAILED array lengths differed, expected.length=0 actual.length=3 junit.framework.AssertionFailedError: array lengths differed, expected.length=0 actual.length=3 at prova.ProvaTest.testSlaDjcl(ProvaTest.java:19)
Characterization  Tests Example (3/5) @Test public void testSlaDjcl() { assertArrayEquals(new int[]{0,0,0},slaDjcl(0.0)); } Testcase: testSlaDjcl(prova.ProvaTest):  Caused an ERROR arrays first differed at element [0]; expected:<0> but was:<1858> arrays first differed at element [0]; expected:<0> but was:<1858> at prova.ProvaTest.testSlaDjcl(ProvaTest.java:19)
Characterization  Tests Example (4/5) @Test public void testSlaDjcl() { assertArrayEquals(new int[]{1858,11,17},slaDjcl(0.0)); } BUILD SUCCESSFUL (total time: 0 seconds)
Characterization  Tests Example (5/5) @Test public void testSlaDjcl() { assertArrayEquals(new int[]{1858,11,17},slaDjcl(0.0)); assertArrayEquals(new int[]{-3617, 1, 24},slaDjcl(-2000000.0)); assertArrayEquals(new int[]{10346, 5, 23},slaDjcl(3100000.0)); assertArrayEquals(new int[]{24309, 9, 19},slaDjcl(8200000.0)); assertArrayEquals(new int[]{38273, 1, 15},slaDjcl(1.33E7)); assertArrayEquals(new int[]{52236, 5, 14},slaDjcl(1.84E7)); assertArrayEquals(new int[]{66199, 9, 10},slaDjcl(2.35E7)); assertArrayEquals(new int[]{80163, 1, 7},slaDjcl(2.86E7)); assertArrayEquals(new int[]{94126, 5, 6},slaDjcl(3.37E7)); assertArrayEquals(new int[]{108089, 9, 1},slaDjcl(3.88E7)); assertArrayEquals(new int[]{122052, 12, 29},slaDjcl(4.39E7)); assertArrayEquals(new int[]{136016, 4, 27},slaDjcl(4.9E7)); assertArrayEquals(new int[]{149979, 8, 25},slaDjcl(5.41E7)); assertArrayEquals(new int[]{163942, 12, 22},slaDjcl(5.92E7)); assertArrayEquals(new int[]{177906, 4, 20},slaDjcl(6.43E7)); assertArrayEquals(new int[]{191869, 8, 16},slaDjcl(6.94E7)); assertArrayEquals(new int[]{205832, 12, 13},slaDjcl(7.45E7)); assertArrayEquals(new int[]{219796, 4, 10},slaDjcl(7.96E7)); assertArrayEquals(new int[]{233759, 8, 8},slaDjcl(8.47E7)); assertArrayEquals(new int[]{247722, 12, 5},slaDjcl(8.98E7)); assertArrayEquals(new int[]{261686, 4, 2},slaDjcl(9.49E7)); }
The TDD algorithm 0. Get the class you want to change under test. 1. Write a failing test case. 2. Get it to compile. 3. Make it pass. (Try not to change existing code as you do this.) 4. Remove duplication. 5. Repeat.
Conclusions: Complaints / Solutions matrix So then you ... But legacy code… add them (as characterization tests) lacks of test redesign it (with refactoring) is ugly
Conclusions: I can’t put code under tests because So you I can’t because code Break Depedencies Use the seams depends of everything Introduce sensing variabiles Use exract method (safe version) lacks of modularity
Thanks Andrea Francia http://andrefrancia.it/ http://blog.andreafrancia.it [email_address] These slide will be available at my blog.

More Related Content

Viewers also liked (7)

PDF
Tutti i miei sbagli, versione 7 Marzo 2012 al XPUG mi
Andrea Francia
 
PDF
Piccolo coding dojo (milano xpug 2013-04-11)
Andrea Francia
 
PDF
Tutti i miei sbagli (Errori di un wannabe Open Source Developer)
Andrea Francia
 
PPT
Subversion @ JUG Milano 11 dic 2009
Andrea Francia
 
PPT
Introduzione al TDD
Andrea Francia
 
PDF
Le 12 pratiche
Andrea Francia
 
PDF
Writing a Crawler with Python and TDD
Andrea Francia
 
Tutti i miei sbagli, versione 7 Marzo 2012 al XPUG mi
Andrea Francia
 
Piccolo coding dojo (milano xpug 2013-04-11)
Andrea Francia
 
Tutti i miei sbagli (Errori di un wannabe Open Source Developer)
Andrea Francia
 
Subversion @ JUG Milano 11 dic 2009
Andrea Francia
 
Introduzione al TDD
Andrea Francia
 
Le 12 pratiche
Andrea Francia
 
Writing a Crawler with Python and TDD
Andrea Francia
 

Similar to Working Effectively with Legacy Code (draft) (20)

PDF
Characterization Testing : regaining control of your Legacy Code [EN]
Elapse Technologies
 
PPTX
Generating characterization tests for legacy code
Jonas Follesø
 
PDF
Software engineering ⊇ Software testing
Pavel Tcholakov
 
PPT
Nighthawk: A Two-Level Genetic-Random Unit Test Data Generator
CS, NcState
 
PDF
Bad test, good test
Seb Rose
 
PPTX
Oleksandr Valetskyy - Increase the quality of your code with property-based t...
Oleksandr Valetskyy
 
PDF
Refactoring In Tdd The Missing Part
Gabriele Lana
 
PDF
"How keep normal blood pressure using TDD" By Roman Loparev
Ciklum Ukraine
 
PPTX
Generatingcharacterizationtestsforlegacycode
Carl Schrammel
 
PDF
Stamp breizhcamp 2019
Caroline Landry
 
PDF
The CI as a partner for test improvement suggestions
Caroline Landry
 
PDF
2013 DevFest Vienna - Bad Tests, Good Tests
Tomek Kaczanowski
 
PDF
Programming with GUTs
catherinewall
 
PDF
Beyond xUnit example-based testing: property-based testing with ScalaCheck
Franklin Chen
 
PDF
Practical unit testing GDC 2014
Andrew Fray
 
PPTX
Pragmatic unittestingwithj unit
liminescence
 
PDF
Input Space Partitioning
Riyad Parvez
 
PDF
Structure and Interpretation of Test Cases
Kevlin Henney
 
PDF
Using Diversity for Automated Boundary Value Testing
Felix Dobslaw
 
PPT
Test Driven
Alex Chaffee
 
Characterization Testing : regaining control of your Legacy Code [EN]
Elapse Technologies
 
Generating characterization tests for legacy code
Jonas Follesø
 
Software engineering ⊇ Software testing
Pavel Tcholakov
 
Nighthawk: A Two-Level Genetic-Random Unit Test Data Generator
CS, NcState
 
Bad test, good test
Seb Rose
 
Oleksandr Valetskyy - Increase the quality of your code with property-based t...
Oleksandr Valetskyy
 
Refactoring In Tdd The Missing Part
Gabriele Lana
 
"How keep normal blood pressure using TDD" By Roman Loparev
Ciklum Ukraine
 
Generatingcharacterizationtestsforlegacycode
Carl Schrammel
 
Stamp breizhcamp 2019
Caroline Landry
 
The CI as a partner for test improvement suggestions
Caroline Landry
 
2013 DevFest Vienna - Bad Tests, Good Tests
Tomek Kaczanowski
 
Programming with GUTs
catherinewall
 
Beyond xUnit example-based testing: property-based testing with ScalaCheck
Franklin Chen
 
Practical unit testing GDC 2014
Andrew Fray
 
Pragmatic unittestingwithj unit
liminescence
 
Input Space Partitioning
Riyad Parvez
 
Structure and Interpretation of Test Cases
Kevlin Henney
 
Using Diversity for Automated Boundary Value Testing
Felix Dobslaw
 
Test Driven
Alex Chaffee
 
Ad

More from Andrea Francia (14)

PDF
Baby Steps TripServiceKata
Andrea Francia
 
PDF
TDD on Legacy Code - Voxxed Days Milano 2019
Andrea Francia
 
PDF
Lavorare con codice legacy “non testabile” - Incontro DevOps - 8 marzo 2019 -...
Andrea Francia
 
PDF
Kata in Bash a DevOpsHeroes 2018 a Parma
Andrea Francia
 
PDF
User Stories - Andrea Francia @ WeDev 7 novembre 2018
Andrea Francia
 
PDF
Le pratiche ingegneristiche di eXtreme Programming
Andrea Francia
 
PDF
Test-Driven Development su Codice Esistente
Andrea Francia
 
PDF
Come si applica l'OCP
Andrea Francia
 
PDF
Le 12 pratiche - Un introduzione a XP (Mini Italian Agile Day)
Andrea Francia
 
PDF
Introduzione a eXtreme Programming
Andrea Francia
 
PDF
Test-Driven Development e Sviluppo Incrementale (TDD-Milano 2017-01-10)
Andrea Francia
 
PDF
Bash-Only Deployment
Andrea Francia
 
PDF
TDD anche su iOS
Andrea Francia
 
PPT
Google C++ Testing Framework in Visual Studio 2008
Andrea Francia
 
Baby Steps TripServiceKata
Andrea Francia
 
TDD on Legacy Code - Voxxed Days Milano 2019
Andrea Francia
 
Lavorare con codice legacy “non testabile” - Incontro DevOps - 8 marzo 2019 -...
Andrea Francia
 
Kata in Bash a DevOpsHeroes 2018 a Parma
Andrea Francia
 
User Stories - Andrea Francia @ WeDev 7 novembre 2018
Andrea Francia
 
Le pratiche ingegneristiche di eXtreme Programming
Andrea Francia
 
Test-Driven Development su Codice Esistente
Andrea Francia
 
Come si applica l'OCP
Andrea Francia
 
Le 12 pratiche - Un introduzione a XP (Mini Italian Agile Day)
Andrea Francia
 
Introduzione a eXtreme Programming
Andrea Francia
 
Test-Driven Development e Sviluppo Incrementale (TDD-Milano 2017-01-10)
Andrea Francia
 
Bash-Only Deployment
Andrea Francia
 
TDD anche su iOS
Andrea Francia
 
Google C++ Testing Framework in Visual Studio 2008
Andrea Francia
 
Ad

Recently uploaded (20)

PDF
Ampere Offers Energy-Efficient Future For AI And Cloud
ShapeBlue
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
TrustArc Webinar - Data Privacy Trends 2025: Mid-Year Insights & Program Stra...
TrustArc
 
PDF
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
PDF
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
PDF
CloudStack GPU Integration - Rohit Yadav
ShapeBlue
 
PDF
HCIP-Data Center Facility Deployment V2.0 Training Material (Without Remarks ...
mcastillo49
 
PDF
Meetup Kickoff & Welcome - Rohit Yadav, CSIUG Chairman
ShapeBlue
 
PDF
Predicting the unpredictable: re-engineering recommendation algorithms for fr...
Speck&Tech
 
PDF
Apache CloudStack 201: Let's Design & Build an IaaS Cloud
ShapeBlue
 
PDF
Building Resilience with Digital Twins : Lessons from Korea
SANGHEE SHIN
 
PDF
Wojciech Ciemski for Top Cyber News MAGAZINE. June 2025
Dr. Ludmila Morozova-Buss
 
PDF
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
PDF
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PPTX
UiPath Academic Alliance Educator Panels: Session 2 - Business Analyst Content
DianaGray10
 
PDF
Blockchain Transactions Explained For Everyone
CIFDAQ
 
PDF
Rethinking Security Operations - SOC Evolution Journey.pdf
Haris Chughtai
 
PDF
Persuasive AI: risks and opportunities in the age of digital debate
Speck&Tech
 
PPTX
Extensions Framework (XaaS) - Enabling Orchestrate Anything
ShapeBlue
 
Ampere Offers Energy-Efficient Future For AI And Cloud
ShapeBlue
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
TrustArc Webinar - Data Privacy Trends 2025: Mid-Year Insights & Program Stra...
TrustArc
 
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
CloudStack GPU Integration - Rohit Yadav
ShapeBlue
 
HCIP-Data Center Facility Deployment V2.0 Training Material (Without Remarks ...
mcastillo49
 
Meetup Kickoff & Welcome - Rohit Yadav, CSIUG Chairman
ShapeBlue
 
Predicting the unpredictable: re-engineering recommendation algorithms for fr...
Speck&Tech
 
Apache CloudStack 201: Let's Design & Build an IaaS Cloud
ShapeBlue
 
Building Resilience with Digital Twins : Lessons from Korea
SANGHEE SHIN
 
Wojciech Ciemski for Top Cyber News MAGAZINE. June 2025
Dr. Ludmila Morozova-Buss
 
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
UiPath Academic Alliance Educator Panels: Session 2 - Business Analyst Content
DianaGray10
 
Blockchain Transactions Explained For Everyone
CIFDAQ
 
Rethinking Security Operations - SOC Evolution Journey.pdf
Haris Chughtai
 
Persuasive AI: risks and opportunities in the age of digital debate
Speck&Tech
 
Extensions Framework (XaaS) - Enabling Orchestrate Anything
ShapeBlue
 

Working Effectively with Legacy Code (draft)

  • 1. Working Effectively with Legacy Code written by Michael Feathers Something I understand about the book
  • 2. Contents The Book Definition of Legacy Code Problems of the Conservative Approach The Automatic Test Approach Example of Characterization Test Breaking Dependencies (not yet ready) Seams (not yet ready) Conclusion: the complaints/solutions matrix
  • 3. The Book Robert C. Martin Series Michael C. Feathers http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052 Paperback:  456 pages Publisher:  Prentice Hall PTR; 1 edition (October 2, 2004)
  • 4. What is legacy code? (for me/us?) Code that: is difficult to understand is fragile is difficult to modify is not (or not well) documented has been inherited from others But that : is still useful!
  • 5. What is legacy code? (M.Feathers) M.Feathers says: Legacy Code ≡ Code without automatic tests Why?
  • 6. The conservative approach No automatic tests leads to Manual testing that leads to High risk of introduce bugs that leads to Fear of change so You prefer add more mess instead cleaning up the existing code and the code get worse, the cost/time of adding features increases If it ain't broke don't fix it
  • 7. Preserving Behaviour with Characterization Tests Write tests for an existings program Write a test that “Describe” the actual behaviour Use these test as regression tests during the refactoring/feature addition. Please note that: “actual” is not always the same as “correct”.
  • 8. Characterization Tests Example (1/5) public static int[] slaDjcl(double djm) { long ld, jd, n4, nd10; if ((djm <= -2395520.0) || (djm >= 1e9)) { throw new IllegalArgumentException(&quot;MJD out of valid range&quot;); } ld = (long) djm; jd = ld + 2400001L; n4 = 4L * (jd + ((6L * ((4L * jd - 17918L) / 146097L)) / 4L + 1L) / 2L - 37L); nd10 = 10L * (((n4 - 237L) % 1461L) / 4L) + 5L; int[] ret = new int[3]; ret[0] = (int) (n4 / 1461L - 4712L); ret[1] = (int) (((nd10 / 306L + 2L) % 12L) + 1L); ret[2] = (int) ((nd10 % 306L) / 10L + 1L); return ret; }
  • 9. Characterization Tests Example (2/5) @Test public void testSlaDjcl() { assertArrayEquals(new int[]{},slaDjcl(0.0)); } Testcase: testSlaDjcl(prova.ProvaTest): FAILED array lengths differed, expected.length=0 actual.length=3 junit.framework.AssertionFailedError: array lengths differed, expected.length=0 actual.length=3 at prova.ProvaTest.testSlaDjcl(ProvaTest.java:19)
  • 10. Characterization Tests Example (3/5) @Test public void testSlaDjcl() { assertArrayEquals(new int[]{0,0,0},slaDjcl(0.0)); } Testcase: testSlaDjcl(prova.ProvaTest): Caused an ERROR arrays first differed at element [0]; expected:<0> but was:<1858> arrays first differed at element [0]; expected:<0> but was:<1858> at prova.ProvaTest.testSlaDjcl(ProvaTest.java:19)
  • 11. Characterization Tests Example (4/5) @Test public void testSlaDjcl() { assertArrayEquals(new int[]{1858,11,17},slaDjcl(0.0)); } BUILD SUCCESSFUL (total time: 0 seconds)
  • 12. Characterization Tests Example (5/5) @Test public void testSlaDjcl() { assertArrayEquals(new int[]{1858,11,17},slaDjcl(0.0)); assertArrayEquals(new int[]{-3617, 1, 24},slaDjcl(-2000000.0)); assertArrayEquals(new int[]{10346, 5, 23},slaDjcl(3100000.0)); assertArrayEquals(new int[]{24309, 9, 19},slaDjcl(8200000.0)); assertArrayEquals(new int[]{38273, 1, 15},slaDjcl(1.33E7)); assertArrayEquals(new int[]{52236, 5, 14},slaDjcl(1.84E7)); assertArrayEquals(new int[]{66199, 9, 10},slaDjcl(2.35E7)); assertArrayEquals(new int[]{80163, 1, 7},slaDjcl(2.86E7)); assertArrayEquals(new int[]{94126, 5, 6},slaDjcl(3.37E7)); assertArrayEquals(new int[]{108089, 9, 1},slaDjcl(3.88E7)); assertArrayEquals(new int[]{122052, 12, 29},slaDjcl(4.39E7)); assertArrayEquals(new int[]{136016, 4, 27},slaDjcl(4.9E7)); assertArrayEquals(new int[]{149979, 8, 25},slaDjcl(5.41E7)); assertArrayEquals(new int[]{163942, 12, 22},slaDjcl(5.92E7)); assertArrayEquals(new int[]{177906, 4, 20},slaDjcl(6.43E7)); assertArrayEquals(new int[]{191869, 8, 16},slaDjcl(6.94E7)); assertArrayEquals(new int[]{205832, 12, 13},slaDjcl(7.45E7)); assertArrayEquals(new int[]{219796, 4, 10},slaDjcl(7.96E7)); assertArrayEquals(new int[]{233759, 8, 8},slaDjcl(8.47E7)); assertArrayEquals(new int[]{247722, 12, 5},slaDjcl(8.98E7)); assertArrayEquals(new int[]{261686, 4, 2},slaDjcl(9.49E7)); }
  • 13. The TDD algorithm 0. Get the class you want to change under test. 1. Write a failing test case. 2. Get it to compile. 3. Make it pass. (Try not to change existing code as you do this.) 4. Remove duplication. 5. Repeat.
  • 14. Conclusions: Complaints / Solutions matrix So then you ... But legacy code… add them (as characterization tests) lacks of test redesign it (with refactoring) is ugly
  • 15. Conclusions: I can’t put code under tests because So you I can’t because code Break Depedencies Use the seams depends of everything Introduce sensing variabiles Use exract method (safe version) lacks of modularity
  • 16. Thanks Andrea Francia http://andrefrancia.it/ http://blog.andreafrancia.it [email_address] These slide will be available at my blog.

Editor's Notes