Refactoring Legacy Code

A presentation at Bulgaria PHP in September 2015 in Sofia, Bulgaria by Adam Culp

Slide 1

Slide 1

Refactoring Legacy Code By: Adam Culp Twitter: @adamculp https://joind.in/talk/a3ecc

Slide 2

Slide 2

Refactoring Legacy Code ● 2 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

Slide 3

Slide 3

Refactoring Legacy Code ● Fan of iteration – 3 Pretty much everything requires iteration to do well: ● Long distance running ● Judo ● Development ● Evading project managers ● Refactoring!

Slide 4

Slide 4

Refactoring Legacy Code ● 6 Modernizing – “Modernizing Legacy Applications in PHP” on LeanPub – by Paul M. Jones – http://mlaphp.com

Slide 5

Slide 5

Refactoring Legacy Code ● What is “Legacy Code” – 7 Is there a coding standard for your project?

Slide 6

Slide 6

Refactoring Legacy Code ● 8 What is “Legacy Code” – Is there a coding standard for your project? – Is code using OOP?

Slide 7

Slide 7

Refactoring Legacy Code ● 9 What is “Legacy Code” – Is there a coding standard for your project? – Is code using OOP? – Is Composer used in your project?

Slide 8

Slide 8

Refactoring Legacy Code ● 10 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?

Slide 9

Slide 9

Refactoring Legacy Code ● 11 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?

Slide 10

Slide 10

Refactoring Legacy Code ● 12 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?

Slide 11

Slide 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? – Does your project avoid NIH? If you can answer “No” to any of these, you may be creating “Legacy Code”!!! 13

Slide 12

Slide 12

Refactoring Legacy Code ● 14 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

Slide 13

Slide 13

Refactoring Legacy Code ● 15 Two hats – Adding Functionality Hat – Refactoring Hat – We add functionality, then refactor, then add more functionality …

Slide 14

Slide 14

Refactoring Legacy Code ● 16 Then optimize – Do not optimize while refactoring. – Separate step. – Refactoring is NOT optimizing.

Slide 15

Slide 15

Refactoring Legacy Code ● 17 Source Control – Refactor in branch – Allows rollback

Slide 16

Slide 16

Refactoring Legacy Code ● 18 Editor/IDE – Makes searching easier – Search within project

Slide 17

Slide 17

Refactoring Legacy Code ● Style Guide – 19 Framework Interop Group ● http://php-fig.org ● PSR – Faster reading – United team

Slide 18

Slide 18

Refactoring Legacy Code ● 20 Testing – Consistent results – Prevents breaks – Speeds up development

Slide 19

Slide 19

Refactoring Legacy Code ● 21 Modernizing Steps – Autoloading – Consolidate Classes – Cleanup Globals – Replace “new” (instantiation) – Create Tests – Extract SQL – Extract Logic – Replace Remaining “Includes”

Slide 20

Slide 20

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 – ● – – – 22 Use My\Great\Namespace\Name Translates to /My/Great/Namespace/Name.php Class = Name

Slide 21

Slide 21

Refactoring Legacy Code ● Autoloading Approaches – – 23 Approaches ● Global function ● Closure ● Static or Instance Method (preferred, if possible) ● __autoload() - PHP v 5.0 Need a central place for classes

Slide 22

Slide 22

Refactoring Legacy Code ● Consolidate Classes – Move to one location ● 24 Could be named “includes”, “classes”, “src”, “lib”, etc.

Slide 23

Slide 23

Refactoring Legacy Code ● Consolidate Classes Step 1 – Search for include statements ● 25 (include, include_once, require, require_once)

Slide 24

Slide 24

Refactoring Legacy Code ● 26 Consolidate Classes Step 2

Slide 25

Slide 25

Refactoring Legacy Code ● Consolidate Classes Step 3 – 27 User class is now autoloaded, no more require_once.

Slide 26

Slide 26

Refactoring Legacy Code ● Consolidate Classes Repeat – 28 Search for more instances

Slide 27

Slide 27

Refactoring Legacy Code ● 29 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

Slide 28

Slide 28

Refactoring Legacy Code ● Global Cleanup Step 1 – 30 Search for global reference

Slide 29

Slide 29

Refactoring Legacy Code ● 31 Global Cleanup Step 2 & 3 – Move global call to constructor – Pass values as properties

Slide 30

Slide 30

Refactoring Legacy Code ● Global Cleanup Step 4 – 32 Convert call to a constructor parameter

Slide 31

Slide 31

Refactoring Legacy Code ● 33 Global Cleanup Step 5 – Instantiate new class – Inject as parameter (DI)

Slide 32

Slide 32

Refactoring Legacy Code ● Global Cleanup Repeat – 34 Look for more instances to clean up

Slide 33

Slide 33

Refactoring Legacy Code ● Steps to Replacing “new” 1 Search for “new” 2 Extract instantiation to constructor parameter. (if one time) ● 35 Or extract block of creation code to new Factory class. (if repeated) 3 Update instantiation calls 4 Repeat

Slide 34

Slide 34

Refactoring Legacy Code ● Replacing “new” Step 1 (Single) – 36 Before

Slide 35

Slide 35

Refactoring Legacy Code ● 37 Replacing “new” Step 2 (Single) – Inject Db object into class constructor. (DI) – No longer instantiating within class

Slide 36

Slide 36

Refactoring Legacy Code ● 38 Replacing “new” (Multiple)

Slide 37

Slide 37

Refactoring Legacy Code ● 39 Replacing “new” Step 3 (Multiple) – Create factory – Extract “new” call to new factory

Slide 38

Slide 38

Refactoring Legacy Code ● Replacing “new” Step 4 (Multiple) – 40 Update instantiation calls

Slide 39

Slide 39

Refactoring Legacy Code ● Replacing “new” Step 4 (Multiple) – 41 Call to factory

Slide 40

Slide 40

Refactoring Legacy Code ● 42 Replacing “new” Repeat

Slide 41

Slide 41

Refactoring Legacy Code ● 43 Write Tests – Code is fairly clean – Write tests for entire application – If not testable, refactor ● Extract method ● Replace temp with query ● Etc.

Slide 42

Slide 42

Refactoring Legacy Code ● 44 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

Slide 43

Slide 43

Refactoring Legacy Code ● 45 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

Slide 44

Slide 44

Refactoring Legacy Code ● Replace “includes” – Search for left over includes – If in current class – 46 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

Slide 45

Slide 45

Refactoring Legacy Code ● 47 Additional Possibilities – Can now implement framework – Leverage services – Leverage events – Use Composer

Slide 46

Slide 46

Refactoring Legacy Code ● 48 Why refactor – Less bugs – Faster development – More stable – Easier onboarding – Save $$$

Slide 47

Slide 47

Refactoring Legacy Code ● 49 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

Slide 48

Slide 48

Refactoring Legacy Code ● 50 Challenges – Manager Buy In – Technical Challenge – Social Challenge

Slide 49

Slide 49

Refactoring Legacy Code ● Convince the boss – 51 Three kinds of managers: ● Tech Savvy ● Quality Centric ● Time Driven Right…

Slide 50

Slide 50

Refactoring Legacy Code ● 52 Tech Savvy boss – Lower cyclomatic complexity – SOLID – Separation of concerns – MVC/Framework – Less bugs – Easier onboarding

Slide 51

Slide 51

Refactoring Legacy Code ● 53 Quality Centric boss – Code quality – Tests – Happier customers – Less bugs

Slide 52

Slide 52

Refactoring Legacy Code ● 54 Time driven boss – Faster feature delivery – Higher productivity - less time reading – Faster onboarding – Less testing time – Less debugging

Slide 53

Slide 53

Refactoring Legacy Code ● 55 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!

Slide 54

Slide 54

● Thank you! – Please rate at: https://joind.in/talk/a3ecc Adam Culp http://www.geekyboy.com http://RunGeekRadio.com Twitter @adamculp Questions?