Refactoring Deciding what to make a superclass or interface is difficult. Some of these refactorings...
-
Upload
darren-stone -
Category
Documents
-
view
217 -
download
2
Transcript of Refactoring Deciding what to make a superclass or interface is difficult. Some of these refactorings...
Refactoring
Deciding what to make a superclass or interface is difficult. Some of these refactorings are helpful.
Some research items include
Inheritance vs Interfaces
Delegation vs Inheritance
Depth of Inheritance Tree
Inheritance
Refactoring
Summary:
You have a type code that affects the behavior of a class.
Replace the type code with subclasses.
Replace Type Code with Sub-Class
Refactoring
Replace Type Code with Sub-Class:
Motivation:
You have a type code that affects the behavior. It is indicated by a group of case like conditional statements. May have switches and/or if then conditional statements and each of the type codes or type code executes a different group of code.
Refactoring
Replace Type Code with Sub-Class: Example: class Employee…
private int _type;
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
Employee (int type) { _type=type;}
int getType ( ) { return _type; }
First step is to use Self Encapsulate Field on the type code
Refactoring
Replace Type Code with Sub-Class: Example:
Employee create (int type) { return new Employee (type);
private Employee (int type) { _type – type; }
Class Engineer extends Employee {
int get Type() { return Empolyee.ENGINEER; }
}
Replace employee’s constructor with a factory method
Start with engineer as a subclass and create the subclass and the overriding method for the type code.
Refactoring
Replace Type Code with Sub-Class: Example:
Class Employee
static Employee create (int type) {
If (type == ENGINEER) return new Engineer();
else return new Employee (type);
}// end create
Alter the factory method to create the appropriate objects.
Refactoring
Replace Type Code with Sub-Class: Example:
Abstract int getType();
Static Empployee create (int type) {
switch (type) {
case ENGINEER: return new Engineer();
case SALESMAN: return new Salesman();
case MANAGER: return new Manager();
default: throw new IllegalArgumentException (“Incorrect type code value”);
} // end case
} // end create
Replace codes with subclasses. Eliminate employee type code field and make getType abstract. Factory method is:::
Refactoring
Replace Type Code with Sub-Class:
Mechanics:
Self encapsulate the type code
For each type code value create subclasses
Remove type code field from superclass and declare accessors for the type code as abstract.
Compile and test.
Refactoring
Summary:
You have subclasses that vary only in methods that return constant data.
Change the methods to superclass fields and eliminate the subclasses.
Replace Sub-Class with Fields
Refactoring
Replace Sub-Class with Fields:
Motivation:
You create subclasses to add features to allow behavior to vary. One form of variant behavior is the constant method. This constant method is one that returns a hard-coded value.
You can remove the subclasses completely by putting fields in the subclass thus removing additional complexity.
Refactoring
Replace Sub-Class with Fields: abstract class Person {
abstract boolean isMale();
abstract char getCode();
…..
class Male extends Person {
boolean isMale(); return true; }
char getCode() { return “M”; }
} // end male
class Female extends Person {
boolean isMale(); return false; }
char getCode() { return “F”; }
} // end female
Refactoring
Replace Sub-Class with Fields:
class Person {
static Person createMale() { return new Male(); }
static Person createFemale() { return new Female(); }
Person kent = new Male();
Person kent = Person.createMale();
Replace constructor with factory. Use a factory for each subclass/
Place calls in the form of:
With calls in the form of:
Refactoring
Replace Sub-Class with Fields:
class Person {
private final boolean _isMale;
private final char _code;
class Person {
protected Person (boolean isMale, char code) {
_isMale = isMale;
_code = code;
}// end Person
Declare fields for each constant method on the superclass.
Add protected constructor
Refactoring
Replace Sub-Class with Fields:
class Male {
Male () { super (true, ‘M’); }
class Female {
Female () { super (false, ‘F’); }
class Person ….
boolean isMale() { return _isMale; }
class Male….
boolean isMale () { return true; }
Add constructors that call this new constructor.
Put accessor on the superclass and eliminate subclass methods.
Refactoring
Replace Sub-Class with Fields:
class Person
static Person createMale () {
return new Person (true, ‘M’);
}
Remove the abstract marker and use inline method to inline subclass constructor.
RefactoringReplace Sub-Class with Fields:
Mechanics:
Use Replace constructor with factory method
If references to subclass, replace with superclass
Declare fields for each constant method and implement
Declare protected superclass constructor
Add or modify sub class constructors
Use inline method to inline constructor
Remove the subclass
Compile and test.
Refactoring
Summary:
Two subclasses have the same field.
Move the field to the superclass.
Pull up Field
Refactoring
Pull up Field:
Motivation:
Subclasses are developed independently and through refactoring you find duplicate features. Such fields sometimes have similar names.
If they are being used in a similar way, you can generalize them.
Refactoring
Employee
ENGINEER__________name()
SALESMAN____________name()
Employee--------------
name()
ENGINEER SALESMAN
Pull up Field
Refactoring
Pull up Field:
Mechanics:
Inspect all uses of the candidate fields to ensure they are used in the same way.
If the fields do not have the same name, rename the fields so that they have the name you want to use for the superclass field.
Create a new field in the superclass.
Delete the subclass fields
Consider using SelfEncapsulateField on the new field.
Refactoring
Summary:
You have methods with identical results on subclasses.
Move them to the superclass.
Pull up Method
Refactoring
Pull up Method:
Motivation:
Eliminating duplicate behavior is important. Where there is duplication, the risk is that alteration to one will not be made to the other.
If you have similar methods , try to pull the methods up to the superclass from the subclass.
Refactoring
Pull up Method:
Employee
ENGINEER__________getName()
SALESMAN____________getName()
Employee--------------getName()
ENGINEER SALESMAN
Refactoring
Pull up Method:
Mechanics:
Inspect the methods to ensure they are identical.
If methods have different signatures, change superclass signature.
Create a new method in superclass, copy body of method to it.
Delete subclass methods.
Take a look at the callers of this method to see whether you can change a required type to the superclass.
Refactoring
Summary:
You have constructors on subclasses with mostly identical bodies.
Create a superclass constructor; call this from the subclass methods.
Pull up Constructor Body
Refactoring
Pull up Constructor Body:
Motivation:
When a constructor has comon behavior , you need a superclass constructor that is called by subclasses.
Refactoring
Pull up Constructor Body:
class Manager extends Employee..
public Manager (String name, String id, int grade) {
_name = name;
_id = id;
_grade = grade;
} // end Manager
Public Manager (String name, String id, int grade) {
super (name, id);
)grade – grade;
} // end Manager
Given
GOES TO
Refactoring
Pull up Constructor Body:
Mechanics:
Define a subclass constructor
Move the common code at the beginning from the subclass to the superclass construtor.
Call the superclass constructor as a first step in the subclas constructor.
Compile and test.
Refactoring
Summary:
Behavior on a superclass is relevant only for some of its subclasses.
Move it to those subclasses.
Pull Down Method
Refactoring
Pull Down Method
Motivation:
You neeed to move behavior from a superclass to a specific subclass.
Refactoring
Pull Down Method
Employee
ENGINEER__________getName()
SALESMAN____________getName()
Employee--------------getName()
ENGINEER SALESMAN
Refactoring
Pull Down Method
Mechanics:
Declare a method in all subclasses and copy the body into each subclass.
Remove metod from superclass.
Remove the method from each subclass that does not need it
Compile and test.
Refactoring
Summary:
A field is used only by some subclasses,
Move the field for those subclasses.
Push Down Field
Refactoring
Push Down Field:
Motivation:
Used when you don’t need a field in the superclass but only in the subclass.
Refactoring
Push Down Field:
Employee
ENGINEER__________getName()
SALESMAN____________getName()
Employee--------------getName()
ENGINEER SALESMAN
Refactoring
Push Down Field:
Mechanics:
Declare the field in all subclasses.
Remove the field from the superclass.
Remove the field from all subclasses that don’t need it.
Compile and test.
Refactoring
Summary:
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.
Extract Subclass
Refactoring
Extract Subclass:
Motivation:
The class has behavior used for some instances of the class and not for others.
A subclass can be created for these behaviors.
Refactoring
Extract Subclass: Job Item
--------------getTotalPrice()getUnitPrice()
Labor Item__________getUnitPrice()getEmployee
JobItem--------------
getItemPrice()getUnitPrice()getEmployee()
RefactoringExtract Subclass:
Mechanics:
Define a new subclass of the sources class
Provide constructors by the new subclass
Find calls to superclass constructors , replace with new constructor.
Use PushDownMethod and PushDownField on subclass features
Review booleans, eliminate by SelfEncapsulateField, replace getter with polymorphic constant methods. Refactor users with Replace Conditional with Polymorphism
Compile and Test after each push down.
Refactoring
Summary:
You have two classes with similar features.
Create a superclass and move the common features in the superclass.
Extract Superclass
Refactoring
Extract Superclass:
Motivation:
Duplicate code is one of the principal bad things in systems.
One form of duplicate code is two classes that do similar things in the same way or similar things in different ways.
Refactoring
Extract Superclass:
Party
Employee__________getAnnualCost()getId
Department____________getAnnualCost()getHeadCount()
Department--------------getTotalAnnualCost()getName()getHeadCount()
Employee--------------getAnnualCost()getName()getId()
RefactoringExtract Superclass:
Mechanics:
Create a bland abstract superclass, make the original classes subclasses of this superclass.
One by one, use PullUpField, PullUpMethod, and PullUpConstructorBody to move common elements to the superclass.
Examine methods left on the subclasses. See if there are common parts, oif there are you can use ExtractMethod followed by PullUpMethod on the common parts. If the overall flow is similar, you may be able to use FormTemplateMethod.
Refactoring
Summary:
Several clients use the same subset of a class’s interface, or two classes have part of their interfaces in common
Extract the subset into an interface.
Extract Interface
Refactoring
Extract Interface:
Motivation:
Use of only a particular subset of the class’s responsibilities by a group of clients. A class needs to work with any class that can handle certain requests.
Make the subset of responsibilities a thing in its own right, so that it can be made clear in the use of the system.
Refactoring
Extract Interface: Billable---------------getRate()hasSpecialSkill()
Employee__________getRate()hasSpecialSkill ()getName()getDepartment()
Employee--------------getRate()hasSpecialSkill()getName()getDepartment()
Refactoring
Extract Interface:
Mechanics:
Create an empty interface.
Declare the common operations in the interface
Declare the relevant class(es) as implementing the interface.
Declare the relevant class(es) as implementing the interface.
Adjust client type declarations to use the interface.
Refactoring
Summary:
A superclass and subclass are not different.
Merge them together
Collapse Hierarchy
Refactoring
Collapse Hierarchy
Motivation:
Tangled class hierarchy can yield many refactoring opportunities
If the hierarchy adds no values, merge the classes together.
RefactoringCollapse Hierarchy
Mechanics:
Choose class to be removed: the superclass or the subclasses.
Use PullUpField and PullUpMethod or Push DownMethod and PushDownField to remove features and place in merged class.
Adjust references to class to be removed to use the merged class. This affects variable declaration, parameter, types, and constructors.
Remove the empty class
Compile and test
Refactoring
Summary:
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 the superclass, and remove the sub-classing.
Replace Inheritance with Delegation
Refactoring
Replace Inheritance with Delegation:
Motivation:
In some cases the superclass features do not apply to many of the subclasses. If this results in code saying one thing when your intention is another. Using delegation instead, it is clearer since you can control the aspects of the interface to use.
RefactoringReplace Inheritance with Delegation:
Vector------------
isEmpty
Return )vector.isEmpty()
Stack
Vector------------
isEmptyStack
Refactoring
Replace Inheritance with Delegation:
Mechanics:
Create and initiate a subclass field as an subclass instance.
Change each method defined to use the delegate field. Compile and test after changing each method.
Remove subclass delegation and replace the delegate assignment to a new object.
For each subclass method used by a client, add a simple delegating method.
Compile and test.
Refactoring
Summary:
You’re using delegation and are often writing many simple delegations for the entire interface.
Method the delegating class a subclass of the delegate.
Replace Delegation with Inheritance
Refactoring
Replace Delegation with Inheritance:
Motivation:
Flip side of replace Inheritance with Delegation. You find you are using all methods of the delegate and have a propondance of delegations and a inheritance is easier to understand.
Refactoring
Replace Delegation with Inheritance:
Vector------------
isEmpty
Return )vector.isEmpty()
Stack
Vector------------
isEmptyStack
Refactoring
Replace Delegation with Inheritance:
Mechanics:
Make the delegating object a subclass of the delegate
Set the delegate field to be the object itself.
Remove the simple delegation methods.
Replace all other delegations with calls to the object itself.
Remove the delegate field.