Successfully reported this slideshow.

Bye Bye Cowboy Coder Days! (Legacy Code & TDD)

3

Share

Loading in …3
×
1 of 34
1 of 34

Bye Bye Cowboy Coder Days! (Legacy Code & TDD)

3

Share

Download to read offline

Description

Bye Bye Cowboy-Coder days! by Vytautas Dagilis.

„Working Effectively with Legacy Code“- one of the best books which talks about Unit testing and TDD. Presentation covers best practices listed in the book as well as shows which of them were successfully implemented in practice. You will find out how to commit changes and be sure that they work even without running and testing application itself.

Transcript

  1. 1. Bye Bye Cowboy-Coder days!
  2. 2. What do developers do for living? Change the code!
  3. 3. Four Reasons to Change Software • Adding a feature • Fixing a bug • Improving the design • Optimizing resource usage
  4. 4. Changing Software Adding a Feature Fixing a Bug Refactoring Optimizing Structure Changes Changes Changes New Changes Functionality Functionality Changes Resource Usage Changes
  5. 5. Preserving behavior Existing Behavior New Behavior
  6. 6. Risky Change 1. What changes do we have to make? 2. How will we know that we've done them correctly? 3. How will we know that we haven't broken anything?
  7. 7. How?
  8. 8. Working with Feedback! Yes, Unit Tests…
  9. 9. Few qualities of Unit Tests • They run fast • They help us localize problems
  10. 10. Dependencies… • No way to run separately • Takes time to load • Hard to localize problem
  11. 11. GUI Tests Integration Tests Unit Tests
  12. 12. GUI Tests Integration Tests Unit Tests
  13. 13. Lag Time Time to fix/Price 1 Minute 10 Minutes 1 Hour 1 Day 1 Week Time to fix/Price
  14. 14. The Legacy Code Dilemma When we change code, we should have tests in place. To put tests in place, we often have to change code.
  15. 15. The Legacy Code Change Algorithm 1. Identify change points 2. Find test points 3. Break dependencies 4. Write tests 5. Make changes and refactor
  16. 16. Sensing and Separation • We break dependencies to sense when we can't access values our code computes • We break dependencies to separate when we can't even get a piece of code into a test harness to run
  17. 17. Faking Collaborators • Fake Objects • Mock Objects • Nothing!
  18. 18. Sprout
  19. 19. Sprout Method 1. Identify where to change 2. Wdown a method call and then comment it out. 3. Determine what local variables you need for the call 4. Determine return value 5. Develop the sprout method using test-driven development 6. Remove the comment in the source method
  20. 20. Sprout Class 1. Identify where you need to make your code change. 2. Write class in that place, and call a method; then comment those lines out 3. Determine what local variables you need from the source method, and make them arguments to the classes' constructor 4. Determine return values to the source method and add a call in the source method to receive those values. 5. Develop the sprout class test first 6. Remove the comment in the source
  21. 21. Wrap
  22. 22. Wrap Method 1. Identify a method you need to change 2. If the change can be formulated as a single sequence of statements in one place, develop a new method for it using test-driven development 3. Create another method that calls the new method and the old method
  23. 23. Wrap Class 1. Identify a method where you need to make a change. 2. Create a class that accepts the class you are going to wrap as a constructor argument. 3. Create a method on that class, using test-driven development. 4. Write another method that calls the new method and the old method on the wrapped class 5. Instantiate the wrapper class in your code in the place where you need to enable the new behavior
  24. 24. TDD and Legacy Code 1. Get the class you want to change under test 2. Write a failing test case 3. Get it to compile 4. Make it pass (Try not to change existing code as you do this) 5. Remove duplication 6. Repeat
  25. 25. Allways check if tests are testing 1. Write test and new code in separate changelist 2. Shelve new code change list 3. Ensure tests are failing
  26. 26. Characterization Tests 1. Use a piece of code in a test harness 2. Write an assertion that you know will fail - let the failure tell you what the behavior is 3. Change the test so that it expects the behavior that the code produces 4. Repeat
  27. 27. I Can't Get This Class into a Test Harness • Lean on the Compiler • Extract Interface • Extract Implementer • Subclass and Override Method • Parameterize Constructor • Parameterize Method • Extract and Override Getter • Extract and Override Factory Method • Singleton Design Pattern
  28. 28. When All Else Fails, Do Some Scratch Refactoring
  29. 29. Questions?
  30. 30. Agile Turas Lietuvoje • Agile Tour Kaunas – rugsėjo 25 d. • Agile Tour Vilnius – spalio 9 d. • Agile Master Classes www.agileturas.lt
  31. 31. The World’s Best Intro to TDD • J. B. Rainsberger, Kanada • 2 Dienų mokymai, Kaune • Rugsėjo 23 - 24 d. www.agileturas.lt/master-classes

Editor's Notes

  • A unit test that takes 1/10th of a second to run is a slow unit test. If you have a project with 3,000 classes and there are about 10 tests apiece, that is 30,000 tests. How long will it take to run all of the tests for that project if they take 1/10th of a second apiece? Close to an hour.

    Elaborate more on problem localization
  • Realybėje tai pasidaro dar panašiau į tai...
  • Lag time is the amount of time that passes between a change that you make and the moment that you get real feedback about the change
  • Generally, when we want to get tests in place, there are two reasons to break dependencies: sensing and separation.
  • One of the most valuable things about TDD is that it lets us concentrate on one thing at a time.
    We are either writing code or refactoring; we are never doing both at once.
    That separation is particularly valuable in legacy code because it lets us write new code
    independently of new code.
    After we have written some new code, we can refactor to remove any duplication between it and
    the old code.
  • Usually unexpected behavior IS expected from the whole application!

    If the system has been deployed, you need to examine the
    possibility that someone is depending on that behavior, even though you see it as a bug.

    Know your code better!
  • Best way to get familiar with the code!
  • Description

    Bye Bye Cowboy-Coder days! by Vytautas Dagilis.

    „Working Effectively with Legacy Code“- one of the best books which talks about Unit testing and TDD. Presentation covers best practices listed in the book as well as shows which of them were successfully implemented in practice. You will find out how to commit changes and be sure that they work even without running and testing application itself.

    Transcript

    1. 1. Bye Bye Cowboy-Coder days!
    2. 2. What do developers do for living? Change the code!
    3. 3. Four Reasons to Change Software • Adding a feature • Fixing a bug • Improving the design • Optimizing resource usage
    4. 4. Changing Software Adding a Feature Fixing a Bug Refactoring Optimizing Structure Changes Changes Changes New Changes Functionality Functionality Changes Resource Usage Changes
    5. 5. Preserving behavior Existing Behavior New Behavior
    6. 6. Risky Change 1. What changes do we have to make? 2. How will we know that we've done them correctly? 3. How will we know that we haven't broken anything?
    7. 7. How?
    8. 8. Working with Feedback! Yes, Unit Tests…
    9. 9. Few qualities of Unit Tests • They run fast • They help us localize problems
    10. 10. Dependencies… • No way to run separately • Takes time to load • Hard to localize problem
    11. 11. GUI Tests Integration Tests Unit Tests
    12. 12. GUI Tests Integration Tests Unit Tests
    13. 13. Lag Time Time to fix/Price 1 Minute 10 Minutes 1 Hour 1 Day 1 Week Time to fix/Price
    14. 14. The Legacy Code Dilemma When we change code, we should have tests in place. To put tests in place, we often have to change code.
    15. 15. The Legacy Code Change Algorithm 1. Identify change points 2. Find test points 3. Break dependencies 4. Write tests 5. Make changes and refactor
    16. 16. Sensing and Separation • We break dependencies to sense when we can't access values our code computes • We break dependencies to separate when we can't even get a piece of code into a test harness to run
    17. 17. Faking Collaborators • Fake Objects • Mock Objects • Nothing!
    18. 18. Sprout
    19. 19. Sprout Method 1. Identify where to change 2. Wdown a method call and then comment it out. 3. Determine what local variables you need for the call 4. Determine return value 5. Develop the sprout method using test-driven development 6. Remove the comment in the source method
    20. 20. Sprout Class 1. Identify where you need to make your code change. 2. Write class in that place, and call a method; then comment those lines out 3. Determine what local variables you need from the source method, and make them arguments to the classes' constructor 4. Determine return values to the source method and add a call in the source method to receive those values. 5. Develop the sprout class test first 6. Remove the comment in the source
    21. 21. Wrap
    22. 22. Wrap Method 1. Identify a method you need to change 2. If the change can be formulated as a single sequence of statements in one place, develop a new method for it using test-driven development 3. Create another method that calls the new method and the old method
    23. 23. Wrap Class 1. Identify a method where you need to make a change. 2. Create a class that accepts the class you are going to wrap as a constructor argument. 3. Create a method on that class, using test-driven development. 4. Write another method that calls the new method and the old method on the wrapped class 5. Instantiate the wrapper class in your code in the place where you need to enable the new behavior
    24. 24. TDD and Legacy Code 1. Get the class you want to change under test 2. Write a failing test case 3. Get it to compile 4. Make it pass (Try not to change existing code as you do this) 5. Remove duplication 6. Repeat
    25. 25. Allways check if tests are testing 1. Write test and new code in separate changelist 2. Shelve new code change list 3. Ensure tests are failing
    26. 26. Characterization Tests 1. Use a piece of code in a test harness 2. Write an assertion that you know will fail - let the failure tell you what the behavior is 3. Change the test so that it expects the behavior that the code produces 4. Repeat
    27. 27. I Can't Get This Class into a Test Harness • Lean on the Compiler • Extract Interface • Extract Implementer • Subclass and Override Method • Parameterize Constructor • Parameterize Method • Extract and Override Getter • Extract and Override Factory Method • Singleton Design Pattern
    28. 28. When All Else Fails, Do Some Scratch Refactoring
    29. 29. Questions?
    30. 30. Agile Turas Lietuvoje • Agile Tour Kaunas – rugsėjo 25 d. • Agile Tour Vilnius – spalio 9 d. • Agile Master Classes www.agileturas.lt
    31. 31. The World’s Best Intro to TDD • J. B. Rainsberger, Kanada • 2 Dienų mokymai, Kaune • Rugsėjo 23 - 24 d. www.agileturas.lt/master-classes

    Editor's Notes

  • A unit test that takes 1/10th of a second to run is a slow unit test. If you have a project with 3,000 classes and there are about 10 tests apiece, that is 30,000 tests. How long will it take to run all of the tests for that project if they take 1/10th of a second apiece? Close to an hour.

    Elaborate more on problem localization
  • Realybėje tai pasidaro dar panašiau į tai...
  • Lag time is the amount of time that passes between a change that you make and the moment that you get real feedback about the change
  • Generally, when we want to get tests in place, there are two reasons to break dependencies: sensing and separation.
  • One of the most valuable things about TDD is that it lets us concentrate on one thing at a time.
    We are either writing code or refactoring; we are never doing both at once.
    That separation is particularly valuable in legacy code because it lets us write new code
    independently of new code.
    After we have written some new code, we can refactor to remove any duplication between it and
    the old code.
  • Usually unexpected behavior IS expected from the whole application!

    If the system has been deployed, you need to examine the
    possibility that someone is depending on that behavior, even though you see it as a bug.

    Know your code better!
  • Best way to get familiar with the code!
  • More Related Content

    Related Books

    Free with a 30 day trial from Scribd

    See all

    Related Audiobooks

    Free with a 30 day trial from Scribd

    See all

    ×