Top Banner
Refactoring: Improving the Design of Existing Code Chapter 11 Dealing with Generalization Abner Huang 2013/10/11
32
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.
Transcript
Page 1: Refactoring Chapter11

Refactoring: Improving the Design of Existing Code

Chapter 11

Dealing with Generalization

Abner Huang

2013/10/11

Page 2: Refactoring Chapter11

Generalization Moving methods around a hierarchy of

inheritance

Pull Up Field

Pull Up Method

Push Down Method

Push Down Field

Pull Up Constructor Body

……

Page 3: Refactoring Chapter11

12 techniques to clean a hierarchy of inheritance

Page 4: Refactoring Chapter11

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

the field to those subclasses.

Page 5: Refactoring Chapter11

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 don’t need it.

Compile and test.

Page 6: Refactoring Chapter11

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

the superclass.

Page 7: Refactoring Chapter11

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

subclasses. Move it to those subclasses

Page 8: Refactoring Chapter11

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.

Page 9: Refactoring Chapter11

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

Move them to the superclass

Page 10: Refactoring Chapter11

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.

Page 11: Refactoring Chapter11

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() {};

Page 12: Refactoring Chapter11

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

}

Page 13: Refactoring Chapter11

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

instances. Create a subclass for that subset of features

Page 14: Refactoring Chapter11

I’ll 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;

}

Page 15: Refactoring Chapter11

We add the following class

class LaborItem ...

public LaborItem (int quantity, Employee employee) {

super (0, quantity, true);

_employee = employee;

}

Page 16: Refactoring Chapter11

get rid of the isLabor field.

class JobItem...

protected boolean isLabor() {

return false;

}

class LaborItem...

protected boolean isLabor() {

return true;

}

Page 17: Refactoring Chapter11

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(); }

Page 18: Refactoring Chapter11

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

superclass and move the common features to the superclass.

Page 19: Refactoring Chapter11

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.

Page 20: Refactoring Chapter11

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();

. . .

Page 21: Refactoring Chapter11

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;

}

Page 22: Refactoring Chapter11

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;

}

Page 23: Refactoring Chapter11

Extract Interface Several clients use the same subset of a class’s interface,

or two classes have part of their interfaces in common.

Page 24: Refactoring Chapter11

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

them together.

Page 25: Refactoring Chapter11

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() { … }

}

Page 26: Refactoring Chapter11

1. Template Method [GoF]:

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

2. Pull up Method

Page 27: Refactoring Chapter11

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);

}

Page 28: Refactoring Chapter11

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.

Page 29: Refactoring Chapter11

Replace Delegation with Inheritance You’re using delegation and are often writing many

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

Page 30: Refactoring Chapter11

A couple of caveats

Don’t use this technique, if you aren’t 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.

Page 31: Refactoring Chapter11