Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TCR is your best friend against legacy

TCR is your best friend against legacy

I'm sure you tried testing your legacy. It's been complicated sometimes, almost impossible. Kent Beck, the creator of TDD, has come with new testing approach: Test Commit or Revert.
And believe me it's really efficient!

In this talk I'll give my feedback based on a real refactoring legacy project with TCR, the tips, the traps.

Khaled Souf

June 07, 2023
Tweet

More Decks by Khaled Souf

Other Decks in Technology

Transcript

  1. 2

  2. ABOUT ME Developer/Crafting Software Coach/Trainer with 13 years Experience working

    for Zenika Montréal Co-organizer of Software Crafters Montréal meetup Co-organizer of SOCRATES Canada unconference more details on : https://ksouf.com 3
  3. 5

  4. 8

  5. LIMBO: SCALING SOFTWARE COLLABORATION (PRINCIPLES) 1. Everyone is working on

    (and production is executing) the same program. 2. No one is allowed to cause others (including users) problems. 3. scales technical collaboration by propagating tiny changes instantly. 9
  6. 11

  7. 13

  8. 14

  9. WHAT IS TCR? 1. a Development Technique (Like TDD) 2.

    invented by Oddmund Strømme, Lars Barlindhaug and Ole Johannessen 3. documented by Kent Beck 15
  10. HOW TCR WORK? 1. write test (with just enough code

    to pass) 2. run the test 3. if Pass Commit else Revert 4. Hidden Rule: it's highly recommended to cheat 16
  11. TCR BY EXAMPLE(1) @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1));

    } ... public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 17
  12. TCR BY EXAMPLE(1) @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1));

    } ... public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 return String.valueOf(toConvertToFizzBuzz); 7 } 8 17
  13. TCR BY EXAMPLE(1) @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1));

    } ... public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 return String.valueOf(toConvertToFizzBuzz); 7 } 8 public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } @Test 1 public void fizzBuzzConvertorLeavesNormalNumbersAlone() { 2 Assert.assertEquals("1", convert(1)); 3 } 4 ... 5 6 7 8 17
  14. TCR BY EXAMPLE(1) @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1));

    } ... public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 return String.valueOf(toConvertToFizzBuzz); 7 } 8 public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } @Test 1 public void fizzBuzzConvertorLeavesNormalNumbersAlone() { 2 Assert.assertEquals("1", convert(1)); 3 } 4 ... 5 6 7 8 17
  15. TCR BY EXAMPLE(1) @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1));

    } ... public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 return String.valueOf(toConvertToFizzBuzz); 7 } 8 public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } @Test 1 public void fizzBuzzConvertorLeavesNormalNumbersAlone() { 2 Assert.assertEquals("1", convert(1)); 3 } 4 ... 5 6 7 8 Pass!!! 17
  16. TCR BY EXAMPLE(1) @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1));

    } ... public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 return String.valueOf(toConvertToFizzBuzz); 7 } 8 public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } @Test 1 public void fizzBuzzConvertorLeavesNormalNumbersAlone() { 2 Assert.assertEquals("1", convert(1)); 3 } 4 ... 5 6 7 8 Pass!!! 17
  17. TCR BY EXAMPLE(1) @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1));

    } ... public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 @Test public void fizzBuzzConvertorLeavesNormalNumbersAlone() { Assert.assertEquals("1", convert(1)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 return String.valueOf(toConvertToFizzBuzz); 7 } 8 public string convert(int toConvertToFizzBuzz) { return String.valueOf(toConvertToFizzBuzz); } @Test 1 public void fizzBuzzConvertorLeavesNormalNumbersAlone() { 2 Assert.assertEquals("1", convert(1)); 3 } 4 ... 5 6 7 8 Pass!!! Commit 17
  18. TCR BY EXAMPLE(2) @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3));

    } ... public string convert(int toConvertToFizzBuzz) { if(toConvertToFizzBuzz%3==0) { return "fizz"; } return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 9 10 11 18
  19. TCR BY EXAMPLE(2) @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3));

    } ... public string convert(int toConvertToFizzBuzz) { if(toConvertToFizzBuzz%3==0) { return "fizz"; } return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 9 10 11 @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 if(toConvertToFizzBuzz%3==0) { 7 return "fizz"; 8 } 9 return String.valueOf(toConvertToFizzBuzz); 10 } 11 18
  20. TCR BY EXAMPLE(2) @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3));

    } ... public string convert(int toConvertToFizzBuzz) { if(toConvertToFizzBuzz%3==0) { return "fizz"; } return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 9 10 11 @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 if(toConvertToFizzBuzz%3==0) { 7 return "fizz"; 8 } 9 return String.valueOf(toConvertToFizzBuzz); 10 } 11 if(toConvertToFizzBuzz%3==0) { return "fizz"; } @Test 1 public void fizzBuzzConvertorMultiplesOfThree() { 2 Assert.assertEquals("Fizz", convert(3)); 3 } 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 7 8 9 return String.valueOf(toConvertToFizzBuzz); 10 } 11 18
  21. TCR BY EXAMPLE(2) @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3));

    } ... public string convert(int toConvertToFizzBuzz) { if(toConvertToFizzBuzz%3==0) { return "fizz"; } return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 9 10 11 @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 if(toConvertToFizzBuzz%3==0) { 7 return "fizz"; 8 } 9 return String.valueOf(toConvertToFizzBuzz); 10 } 11 if(toConvertToFizzBuzz%3==0) { return "fizz"; } @Test 1 public void fizzBuzzConvertorMultiplesOfThree() { 2 Assert.assertEquals("Fizz", convert(3)); 3 } 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 7 8 9 return String.valueOf(toConvertToFizzBuzz); 10 } 11 18
  22. TCR BY EXAMPLE(2) @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3));

    } ... public string convert(int toConvertToFizzBuzz) { if(toConvertToFizzBuzz%3==0) { return "fizz"; } return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 9 10 11 @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 if(toConvertToFizzBuzz%3==0) { 7 return "fizz"; 8 } 9 return String.valueOf(toConvertToFizzBuzz); 10 } 11 if(toConvertToFizzBuzz%3==0) { return "fizz"; } @Test 1 public void fizzBuzzConvertorMultiplesOfThree() { 2 Assert.assertEquals("Fizz", convert(3)); 3 } 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 7 8 9 return String.valueOf(toConvertToFizzBuzz); 10 } 11 Failed!!! 18
  23. TCR BY EXAMPLE(2) @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3));

    } ... public string convert(int toConvertToFizzBuzz) { if(toConvertToFizzBuzz%3==0) { return "fizz"; } return String.valueOf(toConvertToFizzBuzz); } 1 2 3 4 5 6 7 8 9 10 11 @Test public void fizzBuzzConvertorMultiplesOfThree() { Assert.assertEquals("Fizz", convert(3)); } 1 2 3 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 if(toConvertToFizzBuzz%3==0) { 7 return "fizz"; 8 } 9 return String.valueOf(toConvertToFizzBuzz); 10 } 11 if(toConvertToFizzBuzz%3==0) { return "fizz"; } @Test 1 public void fizzBuzzConvertorMultiplesOfThree() { 2 Assert.assertEquals("Fizz", convert(3)); 3 } 4 ... 5 public string convert(int toConvertToFizzBuzz) { 6 7 8 9 return String.valueOf(toConvertToFizzBuzz); 10 } 11 Failed!!! Revert 18
  24. CONTEXT less than a Month more than 100 of Bug

    to fix three deployed applications (Javascript/Java) two Developers (I'm one of them) no prior knowledge about the existing code (or applications) 21
  25. 22

  26. LIMIT OF CLASSIC TCR (IN OUR CASE) 1. needed Red

    Phase 2. almost no production code to produce 23
  27. RED OR REVERT, GREEN OR REVERT 1. write only the

    test 2. run the test 3. if Pass Revert else Commit 4. write enough code to Pass 5. if Pass Commit else Revert 24
  28. WHAT WE LEARNED 1. we didn't need a build server

    2. our code is integrated immediately (Extreme CI) 3. revert Phase is frustrating (but) 25
  29. 26

  30. TAKE AWAY 1. forces you te take small steps 2.

    less merging problems 3. revert Phase is frustrating (but) 27