Refactoring 101

A presentation at Pacific Northwest PHP in September 2015 in Seattle, WA, USA by Adam Culp

Slide 1

Slide 1

Refactoring 101 By: Adam Culp Twitter: @adamculp https://joind.in/14927

Slide 2

Slide 2

Refactoring 101 ● 2 About me – PHP 5.3 Certified – Consultant at Zend Technologies – Organizer SoFloPHP (South Florida) – Organized SunshinePHP (Miami) – Long distance (ultra) runner – Judo Black Belt Instructor

Slide 3

Slide 3

Refactoring 101 ● 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 101 ● 4 About talk – Based on “Refactoring; Improving The Design of Existing Code” book, by Martin Fowler. – https://github.com/adamculp/refactoring101 – for PHP code samples

Slide 5

Slide 5

Refactoring 101 ● 6 What is “refactoring”? – “…process of changing a computer program’s source code without modifying its external functional behavior…” en.wikipedia.org/wiki/Refactoring – Should not add functionality – Simplify code – Improve code readability

Slide 6

Slide 6

Refactoring 101 ● 7 Two hats – Adding Functionality Hat – Refactoring Hat – We add functionality, then refactor, then add more functionality …

Slide 7

Slide 7

Refactoring 101 ● 8 Then optimize – Do not optimize while refactoring – Separate step – Refactoring is NOT optimizing

Slide 8

Slide 8

Refactoring 101 ● 9 Why refactor? – Prevent decay – Preserve or fix design – Reduce duplication – Improve maintainability – Helps us code faster – Locate bugs – Code smells

Slide 9

Slide 9

Refactoring 101 ● Code “smells” – 10 What are “smells”? ● Indications of spoiled code nearby ● Not conclusive ● The “smell” is not bad

Slide 10

Slide 10

Refactoring 101 ● Code “smells” – 11 “Smells” hinting a refactor may be needed: ● Duplicate Code (rule of 3) ● Long Methods ● Large Class ● Long Parameter (argument) List ● Divergent Change – cascade change to accommodate another ● Shotgun Surgery – change ripples as bugs ● Feature Envy – method uses parts from other class ● Switch Statements – sacrifice polymorphism

Slide 11

Slide 11

Refactoring 101 ● Code “smells” – 12 Cont’d: ● Lazy Class – class not doing much ● Speculative Generality – something built for possible future ● Temporary Field/Variable ● Message Chains – object asking object asking object ● Middle Man – directors in place but serve no real purpose ● Inappropriate Intimacy – classes share private parts ● Data Class – getters and setters, but nothing else ● Comments – where comments cover bad code

Slide 12

Slide 12

Refactoring 101 ● Tools to highlight smells – 14 PHPqatools.org ● PHPUnit ● PHPLoc ● PHP_Codesniffer ● PHP_Depend ● PHP Copy/Paste Detector ● PHP Mess Detector ● PHP Dead Code Detector

Slide 13

Slide 13

Refactoring 101 ● Realtime profiling – 15 Zend Z-Ray

Slide 14

Slide 14

Refactoring 101 ● 16 Rewrite vs Refactor – Rewrite = perceived easy road – Refactor = best teacher – Business arguments ● Budget ● Time ● Retain business logic

Slide 15

Slide 15

Refactoring 101 ● When to rewrite – Want a new app ● 17 Not just better coded current app – Business logic change – Target market change – Framework integration or change

Slide 16

Slide 16

Refactoring 101 ● 18 When to refactor? – No “special” time – Short bursts – Refactor to gain something – Prior to adding functionality – When fixing a bug – During code review

Slide 17

Slide 17

Refactoring 101 ● What do I tell my manager? (justification) – Tech savvy manager = not be hard to explain the benefits. – Quality centric manager = stress quality aspects. – 19 ● Introduce as a review process. ● Many resources on Google. Schedule driven manager = Don’t tell (controversial?). ● Find a way to work it in. ● Overall it saves time, but some will never “see” it.

Slide 18

Slide 18

Refactoring 101 ● First steps – – Use source control (Git, SVN, etc.) ● Records steps, provides rollback ● Auditable GET IT WORKING ● 20 Do NOT refactor broken – Create consistent data – Create tests

Slide 19

Slide 19

Refactoring 101 ● Tests and refactoring – Basic refactor steps ● Ensure tests pass ● Plan refactor ● Implement ● Ensure tests still pass Updating tests if needed – Add more tests to cover newly discovered items Repeat! – ● 21

Slide 20

Slide 20

Refactoring 101 ● Example – Lets look at a code example. – Tips and descriptions during steps. – Our Task: ● Video Rental Company has asked for an HTML representation of their customer statement to be created. Let’s look at the code! 22

Slide 21

Slide 21

Refactoring 101 23

Slide 22

Slide 22

Refactoring 101 24

Slide 23

Slide 23

Refactoring 101 25

Slide 24

Slide 24

Refactoring 101 26

Slide 25

Slide 25

Refactoring 101 27

Slide 26

Slide 26

Refactoring 101 28

Slide 27

Slide 27

Refactoring 101 ● Code summary: What did we see? – 29 Method → statement() ● Too long ● Not reusable for HTML version ● Switch sacrificing polymorphism ● Determining class/type ● Calculating rental price, frequent renter points, grant total

Slide 28

Slide 28

Refactoring 101 ● 30 Additional notes – Cannot change how movies are classified. – Customers always changes, not easy in current state. ● Movie classification ● Frequent renter points ● Rental days per type ● Price calculation

Slide 29

Slide 29

Refactoring 101 ● Objective: – Clean up statement(). ● Shorten – – 31 Extract code to encapsulate functionality Extract business logic to keep DRY

Slide 30

Slide 30

Refactoring 101 ● 32 TEST ! ! !

Slide 31

Slide 31

Refactoring 101 ● Extract method – 33 Moves a functionality to it’s own method. ● Encapsulate calculation of each rental. ● Shorten statement() method.

Slide 32

Slide 32

Refactoring 101 ● Extract method cont’d. – 34 We now have a new method amountFor().

Slide 33

Slide 33

Refactoring 101 ● 35 Rename variables – Renaming $each to $rental – Improves readability. – Relate intent.

Slide 34

Slide 34

Refactoring 101 ● Renaming variables, cont’d. – 36 Renamed $each to $rental, and also changed $thisAmount to become $result for clarity.

Slide 35

Slide 35

Refactoring 101 ● 37 Rename method – Rename amountFor() to getCharge(). – Self documenting.

Slide 36

Slide 36

Refactoring 101 ● Move method – Move getCharge() from Customer to Rental. ● – 38 Relies on Rental data. Already have Rental object, no need to pass $rental.

Slide 37

Slide 37

Refactoring 101 ● Move method cont’d – Now calls getDaysRented() directly. – Returns charge of Rental, as it should. ● 39 Building rental charge in customer was misplaced.

Slide 38

Slide 38

Refactoring 101 ● Replace temp with query – 40 Remove temporary variable and call Rental->getCharge() direct. ● Less future maintenance. ● Makes code clearer.

Slide 39

Slide 39

Refactoring 101 ● Extract method – 41 $frequentRenterPoints calculation extracted to getFrequentRenterPoints(), and move it in the Rental class.

Slide 40

Slide 40

Refactoring 101 ● 42 Replace temp with query – Encapsulate logic and generation of grand total. – Promotes DRY. – Remove $totalAmount temporary variable.

Slide 41

Slide 41

Refactoring 101 ● 43 Replace temp with query – Encapsulate logic and generation of frequent renter points. – Promotes DRY. – Remove $frequentRentalPoints temporary variable.

Slide 42

Slide 42

Refactoring 101 ● 44 Create HTML statement – Create HTML version. – Rename original as text version.

Slide 43

Slide 43

Refactoring 101 ● Execution – 45 Can call either Text or HTML versions.

Slide 44

Slide 44

Refactoring 101 ● Recap – – – Most refactoring reduces code ● More self-documenting ● More flexibility ● More testable 3 loops (getFrequentRenterPoints, getTotalCharge, and statement) ● Isolates calculations ● Enabled multiple statements (text/html) Optimizing and refactoring = different ● – 46 Refactor, then optimize Future = separation of concerns

Slide 45

Slide 45

Refactoring 101 ● 59 Conclusion – Do not refactor a broken application – Always have tests in place prior to refactor ● Unit tests or ● Functional tests or ● Manual tests – Leave code cleaner than you got it – Try NOT to rewrite – Learn to “smell” problems – Love iteration!

Slide 46

Slide 46

● Thank you! – Code: https://github.com/adamculp/refactoring101 – Please rate at: https://joind.in/14927 Adam Culp http://www.geekyboy.com http://RunGeekRadio.com Twitter @adamculp