refactoring-3 by SanjuDudeja


More Info
									Refactoring III

        General philosophy
   A refactoring is just a way of rearranging code
       Refactorings are used to solve problems
       If there’s no problem, you shouldn’t refactor
   The notion of “bad smells” is a way of helping us
    recognize when we have a problem
       Familiarity with bad smells also helps us avoid them in the
        first place
   Refactorings are mostly pretty obvious
       Most of the value in discussing them is just to bring them into
        our “conscious toolbox”
       Refactorings have names in order to crystallize the idea and
        help us remember it
        Duplicated code
   Martin Fowler refers to duplicated code as “Number
    one in the stink parade”
       The usual solution is to apply Extract Method: Create a single
        method from the repeated code, and use it wherever needed
       We’ve discussed some of the details of this (adding a
        parameter list, etc.)
   This adds the overhead of method calls, thus the code
    gets a bit slower
       Is this a problem?
         Making code faster
   “We should forget about small efficiencies, say about 97% of the time:
    premature optimization is the root of all evil.”
           -- Tony Hoare
   Rules of Optimization:
       Rule 1: Don't do it.
       Rule 2 (for experts only): Don't do it yet.
            -- M.A. Jackson
   “More computing sins are committed in the name of efficiency (without
    necessarily achieving it) than for any other single reason--including blind
            -- W.A. Wulf
   Very few programs actually need to be faster
        The only two examples I can think of are game graphics and Blackboard
   Donald E. Knuth pointed out (in 1970) that it is essentially impossible to
    predict where the bottlenecks are in a program--you need to use a profiler to
    actually measure what the code is doing
        Long methods
   Another “bad smell” is the overly long method
   Almost always, you can fix long methods by applying
    Extract Method
       Find parts of the method that seem to perform a single task,
        and make them into a new method
   Potential problem: You may end up with lots of
    parameters and temporary variables
       Temporaries: Consider Replace Temp With Query
       Parameters: Try Introduce Parameter Object and Preserve
        Whole Object
       If all else fails, use Replace Method With Method Object
      Temporary variables
   According to Fowler, temporary variables “tend to
    encourage longer methods, because that’s the only way
    you can get at the temp.”
   If the code fragment you want to extract into a method
    contains references to temporary variables whose scope
    overlaps the fragment, you have to somehow provide
    access to that temporary variable
   Solution: Use the Replace Temp With Query refactoring
       Replace Temp With Query
   Create a method to compute or access the temporary variable

   Example (from Fowler):

   Replace:
      double basePrice = quantity * itemPrice;
      if (basePrice > 1000) return basePrice * 0.95;
      else return basePrice * 0.98;

      if (basePrice () > 1000) return basePrice() * 0.95;
       else return basePrice() * 0.98;
       double basePrice() { return quantity * itemPrice; }
        Introduce Parameter Object
   Problem: You have a method that requires a long
    parameter list
       You may have a group of parameters that go naturally
       If so, make them into an object
   Example: Replace
       public void marry(String name, int age,
                         boolean gender, String name2,
                         int age2, boolean gender2) {...}
       public void marry(Person person1, Person person2) {...}
      Preserve Whole Object
   Problem: You have a method that requires a long
    parameter list
   If you are passing in multiple values from the same
    object, pass the object in instead
   Example: Replace
           sendBill(, customer.address,
                    customer.order, amount);
           sendBill(customer, amount);
        Replace Method With Method Object
   If: you have a long method that uses local variables, and you
    can’t use Extract Method,
   Then: turn the method itself into a object
       Create a new class, named after the method
       Give the new class the following fields:
            A final field to hold the object that the method originally came from
            A field for each temporary variable and parameter in the method
       Write a constructor that takes as parameters the original object and the
        parameters of the original method
       Copy the original method into the new class
       If you need anything from the original object, you have a reference to it
   All the old local variables are now fields of the object
       This makes it easy to decompose the long method into as many methods as
        you want
        Long parameter list
   Long parameter lists are difficult to understand, difficult
    to remember, and make it harder to format your code
   We’ve already discussed some solutions, such as
    Introduce Parameter Object
   Another solution, which we won’t go into in detail, is
    called Replace Parameter With Method
       The idea is that you shouldn’t pass a parameter into a method
        if the method has enough information to compute the
        parameter for itself
        Large class
   Classes can get overly large
       Too many instance variables
       More than a couple dozen methods
       Seemingly unrelated methods in the same class
   Possible refactorings are Extract Class and Extract
   A related refactoring, Extract Interface, can be helpful
    in determining how to break up a large class
        Extract Class
   Extract Class is used when you decide to break one
    class into two classes
       Classes tend to grow, and get more and more data
       Good signs:
            A subset of the data and a subset of the methods seem to go together
            A subset of the data seems to be interdependent
       Useful tests:
            If you removed a method or a particular piece of data, what other fields
             and methods would become nonsense?
            How is the class subtyped?
       The actual refactoring technique involves creating a new
        (empty) class, and repeatedly moving fields and methods into
        it, compiling and testing after each move
        Extract Subclass
   Extract Subclass is used when some behaviors of a
    class are used for certain instances, but not others
       If you have a “type code” that is used to distinguish between
        types of objects, this suggests that a subclass may be
       The type code can be eliminated when you create the
       Extract Subclass should not be used when the instances vary
        in more than one respect
   The basic steps are: Define the subclass, provide
    constructors, and use Push Down Method and Push
    Down Field refactorings
       We won’t go into the details of these refactorings
        Extract Interface
   Extract Interface is used when two or more classes
    share a related set of behaviors
       For example, you might provide two or more types of
        services to your customers, with similar but separate billing
       This suggests a Billable interface
       I hire J&K landscaping to do routine mowing and yard
        clearing; they also remove fallen trees, but bill the job
   Java’s Collections make heavy use of interfaces, as
    you have to do similar things (add, remove, iterate
    over) the elements of Sets, Vectors, Stacks, etc.
        Feature envy
   “Feature envy” is when a method makes heavy use of
    data and methods from another class
       Use Move Method to put it in the more desired class
   Sometimes only part of the method makes heavy use of
    the features of another class
       Use Extract Method to extract those parts that belong in the
        other class
        Primitive Obsession
   Many programmers are reluctant to introduce “little”
    classes that represent things easily represented by
    primitives—telephone numbers, zip codes, money
    amounts, ranges (variables with upper and lower
   If your primitive needs any additional data or behavior,
    consider turning it into a class
       For example, you may want to format your primitive in a
        special way, such as (215)898-0587 or 19104-6389
        More bad smells, I
   Divergent Change: One class keeps being changed in
    different ways for different reasons
       Identify each cause of change, and use Extract Class to isolate
        the required changes for that cause

   Shotgun Surgery: Every time you make a change, you
    have to make a lot of little changes in various classes
       Group all the changes into a single class with Move Method
        and Move Field
        More bad smells, II
   Data Clumps: Data fields that occur together in
    numerous places
       Use Extract Class to group the fields into a single object
       Look for parameter lists that can be abbreviated by using this
        new object, and use Introduce Parameter Object or Preserve
        Whole Object

   Switch Statements: A switch statement is used to do
    different things based on some type flag
       Perhaps the types should be subclasses
       Use Extract Method to isolate the switch statement
       Use Move Method to put it into the class that needs these types
       Use Replace Type Code with Subclasses
        Testing for null
   According to Fowler:
       “The essence of polymorphism is that instead of asking an
        object what type it is and then invoking some behavior based
        on the answer, you just invoke the behavior. The object,
        depending on its type, does the right thing.”
   Unfortunately, if the object might be null, you have to
    test it first, or risk getting a NullPointerException
   An occasional test for null isn’t so bad, but a lot of them
    will clutter up the code and be a nuisance
   Solution: Introduce a “null object”—a real object of the
    correct class (or a subclass of the correct class) that has
    the appropriate behavior
That’s all for now...

To top