Refactoring



             Presentation for:
      South Florida PHP Users Group
                     By:
               Adam Culp
              Twitter: @adamculp
           http://www.geekyboy.com
Refactoring

   Based on popular “Refactoring” Improving The
    Design of Existing Code book, by Martin
    Fowler.
   We will start in the code with an example.
   Tips and descriptions will be handled during the
    example.
   In the example we are tasked with creating an
    HTML representation of the customer
    statement for a movie rental.
Refactoring

   Movie class
       With a new project we take
        a look at the current
        application a customer has
        requested to be changed.
       We start with the Movie
        class.
Refactoring

   Rental class
       Next we look at the Rental
        class.
Refactoring

   Customer class p1
       With a new project we take
        a look at the current app
        that is about to be
        changed.
       Next we look at part 1 of
        the Customer class.
Refactoring

   Customer class p2
       With a new project we take
        a look at the current app
        that is about to be
        changed.
       Next we look at part 2 of
        the Customer class.
Refactoring

   Not terrible for a small quick and dirty application, but
    if part of a larger application we have problems.
   Customer class doing far too much, and statement
    method is too long.
   Impossible to reuse the statement for an HTML
    representation.
   The customer also wants to be able to change how
    they classify movies.
   As experienced developers we know that customers
    will always come back six months from now and want
    it changed in some way.
Refactoring

   Rewrite vs Refactor
       Budget constraint
       Time constraint
       Rewrite is an excuse to NOT dig in someone's code
       Refactor is the best teacher
Refactoring

   First step
       Build tests based on current “working” application,
        so we can verify if we break something.
       Pre-load database with data or create fixtures
        needed for tests, to ensure we have a constant to
        compare test results.
       If we are not starting with a working application you
        must first get the application working prior to
        refactoring. Do not try to refactor a broken
        application or you risk breaking it further, and end
        up with a total rewrite.
Refactoring
   Step 1
       Extract Method to move switch statement to its own method.
Refactoring
   Step 2
       Variable names should make sense. (each > rental, thisAmount > result)
Refactoring
   Step 3
       Extract Method amountFor() to Rental class. It uses information from
        Rental, but no information from Customer. We rename it to more
        meaningful getCharge().
Refactoring
   Step 4
       Call getCharge() directly from statement() instead of using amountFor() as
        a middle man method.
Refactoring
   Step 5
       Replace Temp with Query - Cleanup of call to getCharge(). Eliminate
        temp variables by calling method direct. Less maintenance.
Refactoring
   Step 6
       Extract Method and move frequentRenterPoints to its own method in
        Rental class where it logically belongs.
Refactoring
   Step 7
       We do Replace Temp with Query for totalAmount. Temp variables can be
        a problem and really only serve a purpose within their own routine and
        encourage long, complex routines.
Refactoring
   Step 8
       Also do Replace Temp with Query on frequentRentalPoints to eliminate
        more temp variables.
Refactoring
   Step 9
       We are now able to create the HTML version of the statement, and we
        rename the original to represent a Text version.
Refactoring

   Recap
       Most refactoring reduces code, while we increased it for
        this example.
       We also duplicated a loop to make it happen 4 times
        instead    of     once.     (getFrequentRenterPoints,
        getTotalCharge, getTotalFrequentRenterPoints)
       Optimizing and refactoring are different actions.
        Refactor first, then optimize later if needed.
       More refactoring could further clean up Text and HTML
        statements to DRY it up. (split out header/footer, etc.)
       Still need more refactoring to allow classification
        changes by the customer.
Refactoring
   Step 10
       Move Method on getCharge() because it uses data in Movie, so should be
        in the same class as the data.
Refactoring
   Step 11
       Replace Conditional with Polymorphism on getCharge() because it uses
        data in Movie, so should be in the same class as the data.
Refactoring

   Two hats
       Adding Function Hat
       Refactoring Hat
First we add functionality, they we refactor it, then
add more functionality, ...
Refactoring

   Why Refactor?
       Without refactoring code decays
       As code is changed it loses structure, making it
        harder to see design
                  Regular refactoring preserves design
       Poorly designed = more code due to duplication
                  Reduced code = easier to maintain
                  Reduced code = easier to understand
       Helps find bugs
       Helps us program faster
Refactoring

   When to Refactor?
       Should not set aside time to refactor, it is just
        something we do in short bursts
       Refactor because you want to do something, and
        refactoring helps you do it
                  Often a quick refactor can help developing new
                    functionalities move faster
       Rule of Three → see next slide
Refactoring

   Rule of Three
       When you add function
                  Helps to learn code you need to modify
                  Changes code that prevents the addition
       When you need to fix a bug
                  Make code more understandable
                  Usually highlights the bug
       During code review
                  Code looks good to developer, but maybe not to
                    the team.
                  More concrete results
Refactoring

   What do I tell my manager?
       For a tech saavy manager it may not be hard to
        explain the benefits
       Quality centric manager stress quality aspects
                   Perhaps introduce it as a review process
                   There are many resources on Google about
                     value of reviews, inspections, or software
                     development process
       Schedule driven … Don't tell (controversial?)
                   Find a way to work it into scheduling.
                   Overall it saves time, but some will never “see” it
Refactoring

   Code “smells” as indicators
       Bad code “smells” and is a great way of indicating it
        is time for a refactor.
                   Duplicate Code
                   Long Method
                   Large Class
                   Long Parameter (argument) List
                   Divergent Change - if change is needed in
                     multiple areas to accommodate a change
                   Shotgun Surgery – change causes ripple of other
                     needed changes
                   Feature Envy – a method seems to use another
                     class instead of the one it is in
Refactoring

   Code “smells” as indicators
       More “smells”
                  Data Clumps – if data items tend to accompany
                    one another
                  Primitive Obsession
                  Switch statements
                  Parallel Inheritance Hierarchies – caused when
                    you need to create a subclass of one object
                    because you created a subclass of another
                  Lazy Class – classes that do not do much and do
                    not pay for their extra weight
                  Speculative Generality – constructs built for the
                    sake of possibility later
Refactoring

   Code “smells” as indicators
       More “smells”
                  Temporary Field
                  Message Chains – object asking for object that
                     asks for another object...
                  Middle Man – directors in place but serving no
                     real purpose
                  Inappropriate Intimacy – classes should not deal
                     too much with each others private parts
                  Data Class – getters and setters, but nothing else
                  Comments – where comments are used as
                     deodorant to cover a bad smell
Refactoring

   Tests and Refactoring
       You cannot properly refactor without tests in place.
       Writing tests is the first step of refactoring, and
        should happen as you write the code in the first
        place. (or before, as with TDD)
Refactoring

   Thank you


                   Adam Culp
            http://www.geekyboy.com
           http://github.com/adamculp
                Twitter @adamculp

Refactoring PHP

  • 1.
    Refactoring Presentation for: South Florida PHP Users Group By: Adam Culp Twitter: @adamculp http://www.geekyboy.com
  • 2.
    Refactoring  Based on popular “Refactoring” Improving The Design of Existing Code book, by Martin Fowler.  We will start in the code with an example.  Tips and descriptions will be handled during the example.  In the example we are tasked with creating an HTML representation of the customer statement for a movie rental.
  • 3.
    Refactoring  Movie class  With a new project we take a look at the current application a customer has requested to be changed.  We start with the Movie class.
  • 4.
    Refactoring  Rental class  Next we look at the Rental class.
  • 5.
    Refactoring  Customer class p1  With a new project we take a look at the current app that is about to be changed.  Next we look at part 1 of the Customer class.
  • 6.
    Refactoring  Customer class p2  With a new project we take a look at the current app that is about to be changed.  Next we look at part 2 of the Customer class.
  • 7.
    Refactoring  Not terrible for a small quick and dirty application, but if part of a larger application we have problems.  Customer class doing far too much, and statement method is too long.  Impossible to reuse the statement for an HTML representation.  The customer also wants to be able to change how they classify movies.  As experienced developers we know that customers will always come back six months from now and want it changed in some way.
  • 8.
    Refactoring  Rewrite vs Refactor  Budget constraint  Time constraint  Rewrite is an excuse to NOT dig in someone's code  Refactor is the best teacher
  • 9.
    Refactoring  First step  Build tests based on current “working” application, so we can verify if we break something.  Pre-load database with data or create fixtures needed for tests, to ensure we have a constant to compare test results.  If we are not starting with a working application you must first get the application working prior to refactoring. Do not try to refactor a broken application or you risk breaking it further, and end up with a total rewrite.
  • 10.
    Refactoring  Step 1  Extract Method to move switch statement to its own method.
  • 11.
    Refactoring  Step 2  Variable names should make sense. (each > rental, thisAmount > result)
  • 12.
    Refactoring  Step 3  Extract Method amountFor() to Rental class. It uses information from Rental, but no information from Customer. We rename it to more meaningful getCharge().
  • 13.
    Refactoring  Step 4  Call getCharge() directly from statement() instead of using amountFor() as a middle man method.
  • 14.
    Refactoring  Step 5  Replace Temp with Query - Cleanup of call to getCharge(). Eliminate temp variables by calling method direct. Less maintenance.
  • 15.
    Refactoring  Step 6  Extract Method and move frequentRenterPoints to its own method in Rental class where it logically belongs.
  • 16.
    Refactoring  Step 7  We do Replace Temp with Query for totalAmount. Temp variables can be a problem and really only serve a purpose within their own routine and encourage long, complex routines.
  • 17.
    Refactoring  Step 8  Also do Replace Temp with Query on frequentRentalPoints to eliminate more temp variables.
  • 18.
    Refactoring  Step 9  We are now able to create the HTML version of the statement, and we rename the original to represent a Text version.
  • 19.
    Refactoring  Recap  Most refactoring reduces code, while we increased it for this example.  We also duplicated a loop to make it happen 4 times instead of once. (getFrequentRenterPoints, getTotalCharge, getTotalFrequentRenterPoints)  Optimizing and refactoring are different actions. Refactor first, then optimize later if needed.  More refactoring could further clean up Text and HTML statements to DRY it up. (split out header/footer, etc.)  Still need more refactoring to allow classification changes by the customer.
  • 20.
    Refactoring  Step 10  Move Method on getCharge() because it uses data in Movie, so should be in the same class as the data.
  • 21.
    Refactoring  Step 11  Replace Conditional with Polymorphism on getCharge() because it uses data in Movie, so should be in the same class as the data.
  • 22.
    Refactoring  Two hats  Adding Function Hat  Refactoring Hat First we add functionality, they we refactor it, then add more functionality, ...
  • 23.
    Refactoring  Why Refactor?  Without refactoring code decays  As code is changed it loses structure, making it harder to see design  Regular refactoring preserves design  Poorly designed = more code due to duplication  Reduced code = easier to maintain  Reduced code = easier to understand  Helps find bugs  Helps us program faster
  • 24.
    Refactoring  When to Refactor?  Should not set aside time to refactor, it is just something we do in short bursts  Refactor because you want to do something, and refactoring helps you do it  Often a quick refactor can help developing new functionalities move faster  Rule of Three → see next slide
  • 25.
    Refactoring  Rule of Three  When you add function  Helps to learn code you need to modify  Changes code that prevents the addition  When you need to fix a bug  Make code more understandable  Usually highlights the bug  During code review  Code looks good to developer, but maybe not to the team.  More concrete results
  • 26.
    Refactoring  What do I tell my manager?  For a tech saavy manager it may not be hard to explain the benefits  Quality centric manager stress quality aspects  Perhaps introduce it as a review process  There are many resources on Google about value of reviews, inspections, or software development process  Schedule driven … Don't tell (controversial?)  Find a way to work it into scheduling.  Overall it saves time, but some will never “see” it
  • 27.
    Refactoring  Code “smells” as indicators  Bad code “smells” and is a great way of indicating it is time for a refactor.  Duplicate Code  Long Method  Large Class  Long Parameter (argument) List  Divergent Change - if change is needed in multiple areas to accommodate a change  Shotgun Surgery – change causes ripple of other needed changes  Feature Envy – a method seems to use another class instead of the one it is in
  • 28.
    Refactoring  Code “smells” as indicators  More “smells”  Data Clumps – if data items tend to accompany one another  Primitive Obsession  Switch statements  Parallel Inheritance Hierarchies – caused when you need to create a subclass of one object because you created a subclass of another  Lazy Class – classes that do not do much and do not pay for their extra weight  Speculative Generality – constructs built for the sake of possibility later
  • 29.
    Refactoring  Code “smells” as indicators  More “smells”  Temporary Field  Message Chains – object asking for object that asks for another object...  Middle Man – directors in place but serving no real purpose  Inappropriate Intimacy – classes should not deal too much with each others private parts  Data Class – getters and setters, but nothing else  Comments – where comments are used as deodorant to cover a bad smell
  • 30.
    Refactoring  Tests and Refactoring  You cannot properly refactor without tests in place.  Writing tests is the first step of refactoring, and should happen as you write the code in the first place. (or before, as with TDD)
  • 31.
    Refactoring  Thank you Adam Culp http://www.geekyboy.com http://github.com/adamculp Twitter @adamculp