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

Refactoring Legacy Code

Adam Culp
September 27, 2015

Refactoring Legacy Code

Faced with legacy PHP code many decided to rewrite, thinking it will be easier, but for many reasons this can be very wrong. It can lead to angry developers and managers, never ending projects due to scope creep, and more bad code.

Lets follow an entire journey of refactoring a legacy PHP codebase. We will begin with assessment and why, cover planning how and when, discuss execution and testing, and provide step-by-step examples. Attendees will gain insight and tips on how to handle their own pile of code and refactor happy.

Adam Culp

September 27, 2015
Tweet

More Decks by Adam Culp

Other Decks in Programming

Transcript

  1. 2 Refactoring Legacy Code • About me – PHP 5.3

    Certified – Consultant at Zend Technologies – Zend Certification Advisory Board – Organizer SoFloPHP (South Florida) – Organized SunshinePHP (Miami) – Long distance (ultra) runner – Judo Black Belt Instructor
  2. 3 Refactoring Legacy Code • Fan of iteration – Pretty

    much everything requires iteration to do well: • Long distance running • Judo • Development • Evading project managers • Refactoring!
  3. 6 Refactoring Legacy Code • Modernizing – “Modernizing Legacy Applications

    in PHP” on LeanPub – by Paul M. Jones – http://mlaphp.com
  4. 7 Refactoring Legacy Code • What is “Legacy Code” –

    Is there a coding standard for your project?
  5. 8 Refactoring Legacy Code • What is “Legacy Code” –

    Is there a coding standard for your project? – Is code using OOP?
  6. 9 Refactoring Legacy Code • What is “Legacy Code” –

    Is there a coding standard for your project? – Is code using OOP? – Is Composer used in your project?
  7. 10 Refactoring Legacy Code • What is “Legacy Code” –

    Is there a coding standard for your project? – Is code using OOP? – Is Composer used in your project? – Is the project using a framework?
  8. 11 Refactoring Legacy Code • What is “Legacy Code” –

    Is there a coding standard for your project? – Is code using OOP? – Is Composer used in your project? – Is the project using a framework? – Are you unit testing?
  9. 12 Refactoring Legacy Code • What is “Legacy Code” –

    Is there a coding standard for your project? – Is code using OOP? – Is Composer used in your project? – Is the project using a framework? – Are you unit testing? – Does your project avoid NIH?
  10. 13 Refactoring Legacy Code • What is “Legacy Code” –

    Is there a coding standard for your project? – Is code using OOP? – Is Composer used in your project? – Is the project using a framework? – Are you unit testing? – Does your project avoid NIH? If you can answer “No” to any of these, you may be creating “Legacy Code”!!!
  11. 14 Refactoring Legacy Code • What is “refactoring”? – “...process

    of changing a computer program's source code without modifying its external functional behavior...” en.wikipedia.org/wiki/Refactoring – No functionality added – Code quality
  12. 15 Refactoring Legacy Code • Two hats – Adding Functionality

    Hat – Refactoring Hat – We add functionality, then refactor, then add more functionality ...
  13. 16 Refactoring Legacy Code • Then optimize – Do not

    optimize while refactoring. – Separate step. – Refactoring is NOT optimizing.
  14. 19 Refactoring Legacy Code • Style Guide – Framework Interop

    Group • http://php-fig.org • PSR – Faster reading – United team
  15. 20 Refactoring Legacy Code • Testing – Consistent results –

    Prevents breaks – Speeds up development
  16. 21 Refactoring Legacy Code • Modernizing Steps – Autoloading –

    Consolidate Classes – Cleanup Globals – Replace “new” (instantiation) – Create Tests – Extract SQL – Extract Logic – Replace Remaining “Includes”
  17. 22 Refactoring Legacy Code • Autoloading – Namespaces – PSR-0

    • Legacy code typically used long class names – Usage = My_Long_Class_Name – Translates to “/My/Long/Class/Name.php” – Class = My_Long_Class_Name • If not, then PSR-4 – Use My\Great\Namespace\Name – Translates to /My/Great/Namespace/Name.php – Class = Name
  18. 23 Refactoring Legacy Code • Autoloading Approaches – Approaches •

    Global function • Closure • Static or Instance Method (preferred, if possible) • __autoload() - PHP v 5.0 – Need a central place for classes
  19. 24 Refactoring Legacy Code • Consolidate Classes – Move to

    one location • Could be named “includes”, “classes”, “src”, “lib”, etc.
  20. 25 Refactoring Legacy Code • Consolidate Classes Step 1 –

    Search for include statements • (include, include_once, require, require_once)
  21. 27 Refactoring Legacy Code • Consolidate Classes Step 3 –

    User class is now autoloaded, no more require_once.
  22. 29 Refactoring Legacy Code • Cleanup “Global” Dependencies Steps 1

    Search for global reference 2 Move global calls to constructor 3 Convert global call to a constructor parameter 4 Update global call to a class 5 Instantiate new class and pass as parameter (DI) 6 Repeat
  23. 31 Refactoring Legacy Code • Global Cleanup Step 2 &

    3 – Move global call to constructor – Pass values as properties
  24. 32 Refactoring Legacy Code • Global Cleanup Step 4 –

    Convert call to a constructor parameter
  25. 33 Refactoring Legacy Code • Global Cleanup Step 5 –

    Instantiate new class – Inject as parameter (DI)
  26. 35 Refactoring Legacy Code • Steps to Replacing “new” 1

    Search for “new” 2 Extract instantiation to constructor parameter. (if one time) • Or extract block of creation code to new Factory class. (if repeated) 3 Update instantiation calls 4 Repeat
  27. 37 Refactoring Legacy Code • Replacing “new” Step 2 (Single)

    – Inject Db object into class constructor. (DI) – No longer instantiating within class
  28. 39 Refactoring Legacy Code • Replacing “new” Step 3 (Multiple)

    – Create factory – Extract “new” call to new factory
  29. 43 Refactoring Legacy Code • Write Tests – Code is

    fairly clean – Write tests for entire application – If not testable, refactor • Extract method • Replace temp with query • Etc.
  30. 44 Refactoring Legacy Code • Extract SQL 1 Search for

    SQL 2 Move statement and relevant logic to Gateway class 3 Create test for new class 4 Alter code to use new method 5 Repeat
  31. 45 Refactoring Legacy Code • Extract Logic 1 Search for

    uses of Gateway class outside of Transaction classes 2 Extract logic to Transaction classes 3 Test 4 Write new tests where needed 5 Repeat
  32. 46 Refactoring Legacy Code • Replace “includes” – Search for

    left over includes – If in current class 1 Copy contents into file directly 2 Refactor for: no globals, no 'new', DI, return instead of output, no includes – More often 1 Copy contents of include as-is to new class method 2 Replace with in-line instantiation 3 Search for other uses of same, and update them as well 4 Delete original include file, regression test – Test, create new tests if needed – Repeat
  33. 47 Refactoring Legacy Code • Additional Possibilities – Can now

    implement framework – Leverage services – Leverage events – Use Composer
  34. 48 Refactoring Legacy Code • Why refactor – Less bugs

    – Faster development – More stable – Easier onboarding – Save $$$
  35. 49 Refactoring Legacy Code • When/How to refactor – Ask

    boss for time – “Leave it cleaner than you found it” – Do it on your own, it makes YOUR life easier
  36. 50 Refactoring Legacy Code • Challenges – Manager Buy In

    – Technical Challenge – Social Challenge
  37. 51 Refactoring Legacy Code • Convince the boss – Three

    kinds of managers: • Tech Savvy • Quality Centric • Time Driven Right...
  38. 52 Refactoring Legacy Code • Tech Savvy boss – Lower

    cyclomatic complexity – SOLID – Separation of concerns – MVC/Framework – Less bugs – Easier onboarding
  39. 53 Refactoring Legacy Code • Quality Centric boss – Code

    quality – Tests – Happier customers – Less bugs
  40. 54 Refactoring Legacy Code • Time driven boss – Faster

    feature delivery – Higher productivity - less time reading – Faster onboarding – Less testing time – Less debugging
  41. 55 Refactoring Legacy Code • Concluding Thoughts – Do not

    refactor a broken application – Have tests in place prior to refactor • Unit tests or • Functional tests or • Manual tests – Do things in small steps – Love iteration!
  42. • Thank you! – Please rate at: https://joind.in/14883 Adam Culp

    http://www.geekyboy.com http://RunGeekRadio.com Twitter @adamculp Questions?