Slide 1

Slide 1 text

TCR (TEST && COMMIT || REVERT) YOUR BEST TESTING FRIEND AGAINST LEGACY 1

Slide 2

Slide 2 text

2

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

WHAT IS LEGACY CODE? "a code without tests” -- Michael C. Feathers 4

Slide 5

Slide 5 text

5

Slide 6

Slide 6 text

A LEGACY CODE IS: 1. hard to understand 2. hard to test 3. hard to change 6

Slide 7

Slide 7 text

How do make the changes easy? 7

Slide 8

Slide 8 text

8

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

LIMBO DANCE LIMBO LOWER NOW LIMBO LOWER NOW HOW LOW CAN YOU GO? 10

Slide 11

Slide 11 text

11

Slide 12

Slide 12 text

CAN WE USE TDD? 12

Slide 13

Slide 13 text

13

Slide 14

Slide 14 text

14

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

TCR CHARACTERISTICS no red step many tiny commits (same message/ no message) 19

Slide 31

Slide 31 text

What About using it in a real used codebase? 20

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

22

Slide 34

Slide 34 text

LIMIT OF CLASSIC TCR (IN OUR CASE) 1. needed Red Phase 2. almost no production code to produce 23

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

26

Slide 38

Slide 38 text

TAKE AWAY 1. forces you te take small steps 2. less merging problems 3. revert Phase is frustrating (but) 27

Slide 39

Slide 39 text

THANK YOU FOR ATTENDING Questions ? twitter: @khaledsouf 28

Slide 40

Slide 40 text

No content