Top Banner

Click here to load reader

Refactoring Chapter11

Jul 16, 2015

ReportDownload

Technology

  • Refactoring: Improving the Design of Existing Code

    Chapter 11

    Dealing with Generalization

    Abner Huang

    2013/10/11

  • Generalization Moving methods around a hierarchy of

    inheritance

    Pull Up Field

    Pull Up Method

    Push Down Method

    Push Down Field

    Pull Up Constructor Body

  • 12 techniques to clean a hierarchy of inheritance

  • Push down Field If a field is used only by some subclasses, then move

    the field to those subclasses.

  • Push down Field (cont.) Declare the field in all subclasses.

    Remove the field from the superclass.

    Compile and test.

    Remove the field from all subclasses that dont need it.

    Compile and test.

  • Pull up Field Two subclasses have the same field. Move the field to

    the superclass.

  • Push Down Method Behavior on a superclass is relevant only for some of its

    subclasses. Move it to those subclasses

  • Declare a method in all subclasses and copy the body into each subclass.

    Remove method from superclass.

    Compile and test.

    Remove the method from each subclass that does not need it.

    Compile and test.

  • Pull up Method You have methods with identical results on subclasses.

    Move them to the superclass

  • If the method calls another method that is present on both subclasses but not the superclass, declare an abstract method on the superclass.

    If the method uses a subclass field, use Pull Up Field or Self Encapsulate Field and declare and use an abstract getting method.

  • Pull up Constructor Body You have constructors on subclasses with mostly

    identical bodies. Create a superclass constructor; call this from the subclass methods.

    Use super() in JAVA

    C++ has no super(); it use child_ctor(): parent_ctor() {};

  • class Employee...

    protected String _name;

    protected String _id;

    boolean isPriviliged() {..}

    void assignCar() {..}

    class Manager...

    private int _grade;

    public Manager (String name, String id, int grade) {

    super (name, id);

    _grade = grade;

    if (isPriviliged()) assignCar();

    //every subclass does this

    }

  • Extract Subclass A class has features that are used only in some

    instances. Create a subclass for that subset of features

  • Ill start with a job item class that determines prices for items of work at a local garage. If we have the following code

    class JobItem ...

    public JobItem (int unitPrice, int quantity, boolean isLabor, Employee employee) {

    _unitPrice = unitPrice;

    _quantity = quantity;

    _isLabor = isLabor;

    _employee = employee;

    }

    public int getUnitPrice(){

    return (_isLabor)? _employee.getRate(): _unitPrice;

    }

  • We add the following class

    class LaborItem ...

    public LaborItem (int quantity, Employee employee) {

    super (0, quantity, true);

    _employee = employee;

    }

  • get rid of the isLabor field.

    class JobItem...

    protected boolean isLabor() {

    return false;

    }

    class LaborItem...

    protected boolean isLabor() {

    return true;

    }

  • class JobItem...

    public int getUnitPrice(){

    return (isLabor()) ? _employee.getRate(): _unitPrice;

    }

    replace it with class JobItem...

    public int getUnitPrice(){return _unitPrice; }

    class LaborItem...

    public int getUnitPrice(){return _employee.getRate(); }

  • Extract Superclass You have two classes with similar features. Create a

    superclass and move the common features to the superclass.

  • class Employee...

    public Employee (String name, String id, int annualCost) {

    _name = name;

    _id = id;

    _annualCost = annualCost;

    }

    private String _name;

    private int _annualCost;

    private String _id;

    . . .

    //And their getters.

  • public class Department...

    public Department (String name) {

    _name = name;

    }

    public int getTotalAnnualCost(){

    Enumeration e = getStaff();

    int result = 0;

    while (e.hasMoreElements()) {

    Employee each = (Employee) e.nextElement();

    result += each.getAnnualCost();

    }

    return result;

    }

    private String _name;

    private Vector _staff = new Vector();

    . . .

  • Use Pull Up Constructor Body to assign the name class Party...

    protected Party (String name) { _name = name; }

    private String _name;

    class Department...

    public Department (String name) { super (name); }

    class Employee...

    public Employee (String name, String id, int annualCost) {

    super (name);

    _id = id;

    _annualCost = annualCost;

    }

  • The methods Department.getTotalAnnualCost and Employee.getAnnualCost, do carry out the same intention, so they should have the same name. cannot use Pull Up Method

    Add abstract public int getAnnualCost() to superclass.

    class Department...

    public int getAnnualCost(){

    Enumeration e = getStaff();

    int result = 0;

    while (e.hasMoreElements()) {

    Party each = (Party) e.nextElement();

    result += each.getAnnualCost();

    }

    return result;

    }

  • Extract Interface Several clients use the same subset of a classs interface,

    or two classes have part of their interfaces in common.

  • Collapse Hierarchy A superclass and subclass are not very different. Merge

    them together.

  • Form Template Method You have two methods in subclasses that perform

    similar steps in the same order, yet the steps are different.

    Class Customer {

    public String statement() { }

    public String html_statement() { }

    }

  • 1. Template Method [GoF]:

    Build a template for functions for the same tasks with the same workflow

    2. Pull up Method

  • class Customer...

    public String statement() {

    return new TextStatement().value(this);}

    public String htmlStatement() {

    return new HtmlStatement().value(this);}

    class Statement...

    abstract String headerString(Customer aCustomer);

    abstract String eachRentalString (Rental aRental);

    abstract String footerString (Customer aCustomer);

    public String value(Customer aCustomer) {

    out = headerString(aCustomer);

    while (rentals.hasMoreElements()) {

    out += eachRentalString(each);

    }

    out += footerString(aCustomer);

    }

  • Replace Inheritance with Delegation

    A subclass uses only part of a superclasses interface or does not want to inherit data. Create a field for the superclass, adjust methods to delegate to the superclass, and remove the subclassing.

  • Replace Delegation with Inheritance Youre using delegation and are often writing many

    simple delegations for the entire interface. Make the delegating class a subclass of the delegate.

  • A couple of caveats

    Dont use this technique, if you arent using all the methods of the class to which you are delegating

    beware of is that in which the delegate is shared by more than one object and is mutable.

  • References http://sourcemaking.com/refactoring

    http://en.wikipedia.org/wiki/Category:Software_design_patterns

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.