Refactoring to Patterns - PowerPoint PPT Presentation

1 / 35
About This Presentation
Title:

Refactoring to Patterns

Description:

Miscellany utilities. Creation Patterns ... Miscellany. Low-level refactorings. Chain Constructor. Unify Interface. Extract Parameter ' ... – PowerPoint PPT presentation

Number of Views:71
Avg rating:3.0/5.0
Slides: 36
Provided by: harry8
Category:

less

Transcript and Presenter's Notes

Title: Refactoring to Patterns


1
Refactoring to Patterns
  • CSE301
  • University of Sunderland
  • Harry R Erwin, PhD

2
Introduction
  • Want to use a pattern in an existing programme,
    but dont know how to do it?
  • Dont panicthis lecture will discuss how to
    refactor a programme to introduce a pattern.
  • Resource
  • Kerievsky, J., 2005, Refactoring to Patterns,
    Addison-Wesley.

3
Topics
  • Standard patterns used in refactoring
  • Creationcreation methods, factory, builder, and
    singleton
  • Simplificationcomposition, strategy, decorator,
    state, composite, command
  • Generalizationtemplate, composite, observer,
    adapter, interpreter
  • Protectionsingleton, null object, generalization
  • Accumulation (visitor) patternsat the end if
    time is available.
  • Miscellanyutilities

4
Standard Patterns
  • These two patterns are used in refactoring, but
    are never clearly defined
  • Method Object or Functor
  • Reference and Value Objects

5
Method Object or Functor
  • It is possible to make a method into a class
    instance. This allows you to
  • pass it to other methods as an object,
  • store it in a jump table,
  • save it in a log file,
  • save it in an undo queue, and
  • prioritise it for execution in a priority queue.

6
Functor Implementation
  • The class has constructors or factory methods for
    each possible set of arguments.
  • You can define default values for arguments if
    youre careful.
  • It also has an execute()/do()/perform()/etc.
    method for performing the function. This method
    can accept additional arguments.
  • You can define other methods for converting the
    results to a string, etc.

7
Reference and Value Objects
  • A reference object is a business object like
    customer or account.
  • Each reference object stands for something in the
    real world. You use object identity () to test
    for equality. (equals() defaults to this test.)
    You may have to use a factory method to ensure
    non-duplication of reference objects. Consider
    this in designing your system.
  • A value object stands for something like money,
    defined entirely through its data values (usually
    immutable and declared final). You override
    equals() and hashCode() and use equals() to test
    for equality.

8
Overriding equals() for Value Objects
  • The signature of equals() is
  • public boolean equals(Object obj)
  • You should do the following
  • Test obj for instanceof(YourClass). This will
    return true if obj belongs to your class or a
    subclass. You may need to watch out for
    subclassing here.
  • Typecast obj to YourClass
  • Compare the field values
  • Return true if everything matches, else return
    false.

9
Overriding hashCode() for Value Objects
  • The signature of hashCode() is
  • public int hashCode()
  • If two objects are equal(), they must have the
    same hashCode() values.
  • There are at least three approaches
  • Compute the hashCode() of the component fields
    (you may need to autobox primitive types) and xor
    them together.
  • Compute the hashCode() of toString() applied to
    the component fields (you may need to autobox
    primitive types) and xor them together.
  • Compute a hashCode() arithmetically. See Bloch,
    Effective Java Programming Guide (Addison-Wesley)
    for help.

10
Creation Patterns
  • These refactorings address some of the common
    problems in this area.
  • The Creation Method pattern is new. It describes
    the replacement of a collection of constructors
    with static methods that do the same thing more
    clearly.
  • Factory classes usually implement one or more
    Creation Methods.

11
Replace Constructors with Creation Methods
  • Multiple constructors for a class make it hard to
    choose the right one. Perhaps the class instance
    is supposed to be a reference object.
  • Solution replace the constructors with static
    (or non-static) creation methods that are easier
    to understand. Make the constructors private.
  • These are often called factory methods.
  • It does make object creation for that class
    non-standardized, since the new operator is not
    available.

12
Move Creation Knowledge to Factory
  • Data and code to instantiate a class is sprawled
    across many classes.
  • Move the creation knowledge into a single Factory
    class to encapsulate the creation logic and
    client preferences. Start by writing a static
    creation method. Then create a Factory class and
    move the creation method into it. Chase down all
    the compilation problems that result. Youre
    done.
  • Avoid overuse of the Factory pattern. That will
    overcomplicate your design.

13
Encapsulate Classes With Factory
  • Clients directly instantiate classes that reside
    in one package and implement a common interface.
  • Solution Make the class constructors non-public
    and introduce a Factory class to create them.
    (See java.util.Collections.) Improves
    encapsulation.
  • First use Extract Method on constructor calls and
    then Move Method to move them to the Factory
    class. Make the constructors non-public.
  • Negatives new creation methods are needed for
    new kinds of instances. Also limits client
    customization as source code is unavailable to
    clients.

14
Inline Singleton
  • Too many globals are bad, so youve become
    addicted to Singleton classes. Your code needs
    access to a unique object, but doesnt need a
    global point of access. This is a normal
    situation.
  • Solution Move the Singletons features to a
    class that stores and provides access to the
    object. Delete the Singleton.
  • Use Move Method and Move Field to do this.
  • This does complicate a design when objects need
    to be passed down chains.

15
Simplification
  • Most of your code starts out complicated. The
    goal of these refactorings is to redesign it for
    simplicity.

16
Compose Method
  • You cant understand a methods logic.
  • Solution Transform the logic into a small number
    of intention-revealing steps at the same level of
    detail. Will communicate and simplify what the
    method does.
  • I use Extract Method heavily to do this,
    particularly for GUIs.
  • Leads to many small methods of 5-10 lines. Can
    make debugging a chore.

17
Replace Conditional Logic with Strategy
  • Sign lots of conditional logic in a method.
  • Solution Create a Strategy for each variant and
    delegate the computing to the Strategy instance.
    The Strategies encapsulate the various possible
    conditions. Think about using the Prototype
    pattern to avoid creation overhead.
  • It can complicate a design or algorithm.

18
Move Embellishment to Decorator
  • Code embellishes a classs core responsibility.
  • Solution Move it to a Decorator. Note that the
    Decorator class has to implement the public
    interface of the decorated class, so you may want
    to refactor towards this solution, rather than
    all the way.
  • First create the Decorator class (mucho work).
    Then find where the choice of embellishment is
    made and instead construct a Decorator around the
    base class. Note Decorators may be constructed
    around Decorators.

19
Replace State-Altering Conditionals with State
  • The conditional expressions controlling an
    objects state are complex.
  • Solution Replace the conditionals with State
    classes that represent specific states.
  • Find where the state fields are maintained and
    encapsulate them in an abstract State class. Use
    Extract Subclass to get concrete States. Use Move
    Method to delegate responsibilities to the
    subclasses. Identify state transitions and switch
    the State instance there. Consider using
    Prototype.
  • NB State and Strategy patterns are different!

20
Replace Conditional Dispatcher with Command
  • Conditional logic (if then else or switch) is
    used to dispatch requests and execute actions.
  • Solution Create a command for each action. Store
    in a collection and replace the conditional logic
    with code to fetch and execute commands.
  • This is done using Extract Method over and over
    again. Then you Extract Class on each method.
    Create a Command interface and an execute()
    method for that interface. Build a CommandMap.
    Finally replace the conditional dispatcher with
    logic that selects the Command from the
    CommandMap and executes it.

21
Generalization
  • Converts specific code to general-purpose code.
  • Removes duplicated code.
  • Simplifies and clarifies code.

22
Form Template Method
  • Two methods in subclasses perform similar but not
    identical steps in the same order.
  • Solution Generalize the two methods by
    extracting their steps into methods with
    identical signatures. Use Extract Method to do
    this.
  • Then pull up the generalized methods to form a
    template method in their base class.

23
Replace Hard-Coded Notifications with Observer
  • Subclasses are defined and hard-coded to notify
    an instance of another class of their changes.
    The notified class varies with the subclass
    selected.
  • Solution Remove the subclasses by making their
    superclass capable of notifying any class that
    implements an Observer pattern. The receiver
    classes implement that pattern and register for
    updates.
  • You may need to move logic from the subclass to
    its receiver to allow this to work.

24
Unify Interfaces with Adapter
  • Clients interact with two alternative classes,
    one of which has a preferred or mandatory
    interface.
  • Solution Unify the interfaces with an adapter.
  • Apply Extract Interface to the class with the
    preferred interface.
  • Apply Extract Class to the class that uses the
    alternatives. That creates a primitive Adapter.
  • Use the Adapter instead of the hidden classes.
    Use Move Method to make this happen.
  • Have the Adapter implement the common interface.

25
Protection
  • These refactorings improve the protection of
    existing code.

26
Replace Type Code with Class
  • A fields type (primitive type or String) does
    not protect it from unsafe assignments and
    invalid equality comparisons. This can be a
    particular problem for enumerations.
  • Solution Make the type of the field a class (or
    enum) so you can constrain those unsafe
    operations.
  • Apply Self Encapsulate Field so you use getters
    and setters to access the fieldwhich becomes
    private.
  • Create a concrete class to hold the field.
  • Instantiate in the using class and switch over.

27
Limit Instantiation with Singleton
  • Your code creates multiple instances of an object
    and then uses too much memory or slows down.
  • Solution Replace the multiple instances with a
    Singleton
  • Make sure the state of the object can be shared.
  • Replace the constructor with a creation method.
    Then insert the standard Singleton logic.
  • You also might do this with a Map if you still
    need more than one object. The Singleton contains
    the Map. Note you can decorate the Map with
    immutable when you return it so that its
    read-only.

28
Introduce Null Object
  • Your code has lots of logic for dealing with a
    null field or variable.
  • Solution Replace the null value with a Null
    Object, which has all the necessary methods
    defined and simply does nothing. There are a lot
    of examples of this in javax.swing.
  • Create a NullObject class by applying Extract
    Subclass and/or Extract Interface.
  • Find out what the null checks do in your code and
    have the NullObject class do them.
  • Whenever the field is set to null, set it to an
    instance of the NullObject.
  • You might save a copy of the NullObject in the
    superclass and either share it or clone it to cut
    execution time.
  • Eventually, you will remove the null checks.

29
Miscellany
  • Low-level refactorings
  • Chain Constructor
  • Unify Interface
  • Extract Parameter

30
Chain Constructor
  • You have multiple constructors with duplicate
    code.
  • Solution Chain them together
  • Look for duplication and figure out ways that the
    constructors can call each other to eliminate it.
  • Make any constructors that are internal to this
    process non-public.
  • See the BankingDataReader for an example.

31
Unify Interface
  • You need a superclass or superinterface to have
    the same interface as a subclass.
  • Solution Find all public methods in the subclass
    and put null versions in the superclass.
  • Often a station on a road to someplace else.

32
Extract Parameter
  • A method or constructor assigns a field to a
    locally instantiated value.
  • Solution Assign the field to a parameter
    supplied by a client by extracting one-half of
    the assignment statement to a parameter.
  • The client supplies a null variable to fill in,
    and the constructor or method sets it to the
    value.
  • Its like a website cookie. If the variable is
    final, this can even ensure that it is preserved
    unchanged until it is needed later.
  • Often used in swap algorithms.

33
Accumulation
  • A lot of code accumulates information for a
    summary report
  • Move Accumulation to Collecting Parameter
  • Move Accumulation to Visitor

34
Move Accumulation to Collecting Parameter
  • A bulky method exists that accumulates
    information in a local variable. What to do?
  • A Collecting Parameter is an object that is
    passed to methods to accumulate information from
    them.
  • Often used with Compose Method.
  • Often used for composites.
  • Used in JUnit to accumulate test result
    information.

35
Move Accumulation to Visitor
  • Like the previous refactoring, but the classes
    are heterogeneous.
  • Move the accumulation task to a Visitor.
  • Operates on an object structure, each object
    providing a double dispatch. The visitor is
    passed to the object using an accept(Visitor v)
    method defined by the object, and the object
    calls v.visitType(this), passing itself to the
    appropriate visit method provided by the Visitor.
  • Visitor is rarely needed, but when needed its
    the only good solution. Its needed when you have
    to run several algorithms on the object
    structure. Think XML, generating a test report,
    or logging.
Write a Comment
User Comments (0)
About PowerShow.com