Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and...

77
Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville

Transcript of Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and...

Page 1: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Chapter 6: Code Refactoring

Omar Meqdadi

SE 3860 Lecture 6

Department of Computer Science and Software Engineering University of Wisconsin-Platteville

Page 2: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

2

Topic Covered

Refactoring Refactoring Categories Refactoring Limitations Refactoring Tools

Page 3: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

3

Refactoring

Process of changing a software system in such a way that it Does not alter the external behavior of the code Improves its internal structure

A program restructuring operation to support Design evolution Reuse of object oriented frameworks Preserve the behavioral aspects of the program

Page 4: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring Specifies

Source to source transformation Remain inside the same language, e.g., C++ to C++ Does not change the programs behavior – according to a

test suite Originally designed for object-oriented languages, but

can also be applied to non-object oriented language features, (i.e., functions)

Page 5: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring: Why?

Design Preservation Design Evolution Problems

Code changes often lead to a loss of the original design Loss of design is cumulative:

Difficulties in design comprehension Difficulties in preserving design More rapid decay of design

Solution: Refactoring improves the design of existing code

Page 6: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring: Why?

Comprehension Developer's are most concerned with getting the program

to work, not about future developers Refactoring makes existing code more readable Increases comprehension of existing code, leading higher

levels of code comprehension Often applied in stages

Page 7: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring: Why?

Debugging Improved program comprehension leads to easier

debugging Increased readability leads to the discovery of possible

errors Understanding gained during debugging can be put back

into the code

Page 8: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring: Why?

Faster Programming Counterintuitive argument made by Fowler Good design is essential for rapid development Poor design allows for quick progress, but soon slows the

process down Spend time debugging Changes take longer as you understand the system and find

duplicate code

Page 9: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring: When?

Adding Functionality Comprehension of existing program Preparation for addition

Debugging Comprehension of existing program

Code Review Preparation for suggestions to other programmers Stimulates other ideas Remove bad code smells

Page 10: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring Catalog

Refactoring entry composed of: Name Summary Motivation Mechanics Examples

Page 11: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring: Categories

Composing Methods Creating methods out of inlined code

Moving Features Between Objects Changing of decisions regarding where to put

responsibilities Organizing Data

Make working with data easier

Page 12: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring: Categories

Simplifying Conditional Expressions Making Method Calls Simpler

Creating more straightforward interfaces Dealing with Generalization

Moving methods around within hierarchies Big Refactoring

Refactoring for larger purposes

Page 13: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Composing Methods

Extract Method Inline Method Inline Temp Replace Temp with Query Introduce Explaining Variables Split Temporary Variable Remove Assignments to Parameters Replace Method with Method Object Substitute Algorithm

Page 14: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Remove Assignments to Parameters

Example: Remove Assignments to Parameters

Page 15: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Extract Methods

Create a new method, and name it after the intention of the method (name it by what it does, not by how it does it)

Copy the extracted code from the source method into the new target method

Scan the extracted code for references to any variables that are local in scope to the source method

See whether any temporary variables are used only within this extracted code. If so, declare them in the target method as temporary variables

Page 16: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Extract Methods (cont.)

Look to see whether any local-scope variable are modified by the existing code

Pass into the target method as parameters local scope variables that are read from the extracted code

Compile when you have dealt with all the locally- scoped variables

Replace the extracted code in the source method with a call to the target method

Compile and test

Page 17: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Extract Methods

void compAndPrint() { // compute X // compute Y ... // print X // print Y ... // store X // store Y}

void compute () { // compute X // compute Y print(X, Y); // store X // store Y}

void print(X,Y) { // print X // print Y}

Page 18: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Inline Methods

void compute () { X = next(X); Y = next(Y);}

int next(N) { return N++;}

void compAndPrint() { ... X++; Y++; ...}

Page 19: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Inline Temp

Example:

double basePrice = anOrder.basePrice();return (basePrice > 1000) return (anOrder.basePrice > 1000)

Page 20: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Temp with Query

When: using a temporary variable to hold the result of an expression.

double rectarea = length * width; if (rectarea > 1000) return rectarea * 0.95; else return rectarea * 0.98;

If ( RectArea( ) > 1000 ) return RectArea( ) * 0.95;else return RectArea( ) * 0.98;}

double RectArea( ){ return length * width;}

Page 21: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Split Temp Variable

When: using a temporary variable to hold several expressions.

double temp = 2 * (_height * _widgth);cout << “Perimeter is “ << temp << endl;temp = _height * _width; cout << “Area is “ << temp << endl;

double perimeter = 2 * (_height * _widgth);cout << “Perimeter is “ << perimeter << endl;double area = _height * _width; Cout << “Area is “ << area << endl;

Page 22: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Introduce Explaining Variable

When: You have a complicated expression. Then, Put the result of the expression, or parts of the expression, in a temporary variable with a name that explains the purpose.

// return = baseprice – quantitydiscount + shippingreturn (quantity*price)-((quantity-50)*discount) +price * 0.05

double baseprice = quantity * price;double quantitydiscount = (quantity-50)*discount;double shipping =price * 0.05;return baseprice – quantitydiscount + shipping;

Page 23: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Moving Object Features

Move Method Move Field Extract Class Inline Class Hide Delegate Remove Middle Man Introduce Foreign Method Introduce Local Extension

Page 24: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Move Method

When: if a method is used by another class more than the class on which its defined, move it to the other class

class Student { bool IsEnroll(Course course) { return (course.getStudents().contains(this)); } }

class Course { Student students[size]; Student * getStudents() { return students; } }

class Student { }

public class Course { Student students[size]; bool isEnroll(Student student) { return students.contains(student); } }

Page 25: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Extract Class

class Student{ private: string name; string street; string city; string state; }

class Student{ private: string name; Address address; }

class Address{ private: string street; string city; string state; }

Page 26: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Inline Class

When: a class that isn’t doing too much and shouldn’t be around any more. Then, move all its features to another class. So inline class is the reverse of Extract Class

Page 27: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Hide Delegate

When: a client calls a delegate class of an object Refactoring: create methods on the server to hide the delegate

Client must know about Person and Department

Person must know about department

Client only calls Person

Person calls department

Page 28: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Hide Delegate Class Person {

Department _department;

public Department getDepartment()

{ return _department;}

public void setDepartment (Department arg)

{ _department = arg;}

} // end person

Class Department {

private String _chargeCode;

private Person _manager;

public Department (Person manager)

{ _manager = manager; }

public Person getManager()

{ return _manager; }// end Dept

Client Class:

joe.getDepartment().getManager();

Person Class:

public Person getManager () {

return _department.getManager();

} // end getManager

Client Class:

manager = joe.getManager();

Page 29: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Remove Middle Man

When: after several “Hide delegate”, the server becomes just a middle man for all the delegate methods.

Refactoring: Change the client to call the delegate directly

Client only calls Person

Person calls department

Client must know about Person and Department

Person must know about department

Page 30: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Introduce Foreign Method

When: a server class needs an additional methods, but you can’t modify it

Refactoring: Create the method in the client class Set one of the argument of the method to the instance of

the server class StrDate newStart = new Date

(previousEnd.getYear(),

previousEnd.getMonth(),

previousEnd.getDate()+ 1);

Date newStart = nextDat(previousEnd);

private static Date nextDay (Date arg)

{

return new Date (arg.getYear(),arg.getMonth(),

arg.getDate() + 1);

} // end nextDay

Page 31: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Introduce Local Extension

When: a class needs several additional methods, but you can’t modify it ( such as server class)

Refactoring: Create a new class that contains these additional methods Make the new class a subclass of the original one

(inheritance) or use wrapper approach (delegation)

Page 32: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Organizing Data

Self Encapsulate Field Replace Data Value with Object Change Value to Reference Change Reference to Value Replace Array with Object Duplicate Observed Data Change Unidirectional Association to Bidirectional Change Bidirectional Association to Unidirectional

Page 33: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Organizing Data (cont.)

Replace Magic Number with Symbolic Constant Encapsulate Field Encapsulate Collection Replace Record with Data Class Replace Type Code with Class Replace Type Code with Subclasses Replace Type Code with State/Strategy Replace Subclass with Fields

Page 34: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Change Reference to Value

void swap ( int * x , int * y){ int temp = *x; *x = *y; *y = temp;}void main (){ int a = 5; int b = 7; swap (&a , &b);}

void swap ( int &x , int &y){ int temp = x; x = y; y = temp;}void main (){ int a = 5; int b = 7; swap (a , b);}

Page 35: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Array with Object

String[] row = new String[3];row[0] = “Platteville”;row[1] = “15”;

Performance row = new Performance();row.setName(“Platteville”);row.setWins(“15”);

Page 36: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Encapsulate Field

Page 37: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Magic Number with Constant

Example:

double Energy (double m, double h) {

return m * 9.81 * h;

}

static Final double GRAVITATIONAL_CONSTANT * 9.81;

double Energy (double m, double h) {

return m * GRAVITATIONAL_CONSTANT * h;

}

Page 38: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Simplifying Conditional

Decompose Conditional Consolidate Conditional Expression Consolidate Duplicate Conditional Fragments Remove Control Flag Replace Nested Conditional with Guard Clauses Replace Conditional with Polymorphism Introduce Null Object Introduce Assertion

Page 39: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Decompose Conditional

Example: Decompose Conditional

Page 40: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Consolidate Conditional

double disabilityAmount() { if (_seniority < 2) return 0; if (_monthsDisabled > 12) return 0; if (_isPartTime) return 0; // do smoething else}

double disabilityAmount() {{ if (isNotEligableForDisability()) return 0; // do something else}

bool isNotEligableForDisability(){ if (_seniority < 2 || _monthsDisabled > 12 || _isPartTime() ) return false; else return true;}

Page 41: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Consolidate Duplicate Conditional Fragments

if (isSpecial()) { total = price * 0.95; send(); }else{ total = price * 0.98; send();}

if (isSpecial()) { total = price * 0.95;}else{ total = price * 0.98;}

Send();

Page 42: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Introduce Null Objects

When: for null or default behavior, use inheritance

class Animal { Voice MakeSound() { return voice; } }

Animal obj = new Animal;if (obj == null) voice = Voice.basic();else voice = obj.MakeSound();

class Animal{ Voice MakeSound() { return voice; }}

class NullAnimal : public Animal{ Voice MakeSound() { return Voice.basic(); }}

Page 43: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Nested Conditional with Guard

When: A method has unclear conditional behavior. Then , use Guard Clauses for all the special cases

double getAmount() { double result; if (isDead ()) result = deadAmount(); else { if (isSeparated( ) ) result = separatedAmount(); else { if (isRetired ( ) ) result = retiredAmount(); else result = normalPayAmount(); } } return result;}

double getAmount() { if (isDead ( ) ) return deadAmount(); if (isSeparated ( ) ) return separatedAmount(); if (isRetired ( ) ) return retiredAmount(); return normalPayAmount();}

Page 44: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Conditional with Polymorphism

class Bird {……double getSpeed() { switch (_type) { case EUROPEAN: return getBaseX(); case AFRICAN: return getBaseX() – _number; }}…..

Page 45: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Introduce Assertion

When: the code assumes something. Then, make the assumption explicit with an assertion.

double getExpenseLimit() {

// should have either expense limit or // a primary // project

 return (_expenseLimit != NULL_EXPENSE) ?

        _expenseLimit:

       _primaryProject.getMemberExpenseLimit();

   }

 

double getExpenseLimit() {      

Assert.isTrue (_expenseLimit != NULL_EXPENSE || _primaryProject != null);      

return (_expenseLimit != NULL_EXPENSE) ? 

          _expenseLimit:          

_primaryProject.getMemberExpenseLimit(); 

  }  

Page 46: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Remove Control Flag

When: remove a control flag and use break or return void checkSecurity( ) {      

bool found = false;      

for (int i = 0; i <length; i++) {          

if (! found) {             

if(people[i].equals("Don")){               

sendAlert();               

found = true;   }             

if(people[i].equals ("John")){               

sendAlert();               

found = true;   }

           }     

  }  

}  

void checkSecurity( ) {         

for (int i = 0; i <length; i++) {          

  if(people[i].equals("Don")){               

sendAlert();               

break;   }             

if(people[i].equals ("John")){               

sendAlert();               

break;   }

  }  

}  

Page 47: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Simplifying Method Calls

Rename Method Add Parameter Remove Parameter Separate Query from Modifier Parameterize Method Replace Parameter with Explicit Methods Preserve Whole Object Replace Parameter with Method

Page 48: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Simplifying Method Calls(cont.)

Introduce Parameter Object Remove Setting Method Hide Method Replace Constructor with Factory Method Encapsulate Downcast Replace Error Code with Exception Replace Exception with Test

Page 49: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Remove Setting Method

When: A field should be set at creation time and never altered. Then, remove any setting method for that field.

class Account {   

private String _id;   

Account (String id)

{  setId(id);   }   

void setId (String arg)

{  _id = arg;   }

class Account {   

private String _id;   

Account (String id)

{   _id = arg;   }   

}

Page 50: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Hide Method

When: A method is not used by any other class

Refactoring: Make the method private

Page 51: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Parameterize Method

When: Several methods do similar things but with different values contained in the method body. Then, Create one method that uses a parameter for the different values.

class Employee {

    void tenPercentRaise () {

        salary *= 1.1; }

    void fivePercentRaise () {

        salary *= 1.05;}

}

class Employee {

    void Raise (double factor) {

        salary *= (1+ factor); }

}

Page 52: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Parameter with Explicit Method

When: a method that runs different cases depending on the values of a parameter. Then, create a separate method for each value of the parameter

void setValue (string name, int value) { if (name.equals("height")) height = value; if (name.equals("width")) width = value; }

void setHeight(int value) { height = value;}

void setWidth (int value) { width = value;}

Page 53: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Introduce Parameter Object

When: a group of parameters that naturally go together. Then , replace them with an object

Page 54: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Preserve Whole Object

When: You are getting several values from an object and passing these values as parameters in a method call. Then, send the whole object instead.

int low = daysTempRange.getLow();     

int high = daysTempRange.getHigh();     

withinPlan = plan.withinRange(low, high);  

withinPlan = plan.withinRange(daysTempRange);  

Page 55: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Error Code with Exception

When: A method returns something to indicate an error is better performed with an Exception

bool withdraw(int amount) { if (amount > balance) return false; else { balance -= amount; return true; }}

void withdraw(int amount) throws BalanceException { if (amount > balance) { throw new BalanceException(); } balance -= amount;}

Page 56: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Exception with Test

When: if you are catching an exception that could be handled by an if-statement, use that instead

int getValuebyIndex (int index) { try { return values[index]; } catch (ArrayIndexOutOfBoundsException e) { return 0; }}

int getValuebyIndex (int index) { if (index >= values.length) return 0; return values[index]; }

Page 57: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Constructor with Factory Method

Factory Class: A utility class that creates an instance of a class from a

family of derived classes Useful in a situation that requires the creation of many

different types of objects, all derived from a common base type

Page 58: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Constructor with Factory Method

Class Computer

{

………

};

class Laptop: public Computer

{

………

};

class Desktop: public Computer

{

......

};  

class ComputerFactory {

public:

static Computer *NewComputer(const std::string &description)

{

if(description == "laptop")

return new Laptop;

if(description == "desktop")

return new Desktop;

return NULL;

}

};  

Client Side:

Computer * lapobj = ComputerFactory::NewComputer(“laptop”);

Computer * deskobj = ComputerFactory::NewComputer(“desktop”);

Page 59: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Dealing with Generalization

Pull Up Field Pull Up Method Pull Up Constructor Body Push Down Method Push Down Field Extract Subclass Extract Superclass Extract Interface

Page 60: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Dealing with Generalization

Collapse Hierarchy Form Template Method Replace Inheritance with Delegation Replace Delegation with Inheritance

Page 61: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Method/Field Movement

Pull Up Method/Field When: Two subclasses have the same method/field Refactoring: Move the method/field to the superclass

Push Down Method/Field When: A method/field is only used in subclass Refactoring: move the method/field to the subclass

Page 62: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Method/Field Movement

Example: Push Down Method

Page 63: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Pull Up Constructor Body

When: constructors on subclasses with mostly identical bodies.

Refactoring: Create a superclass constructor; call this from the subclass

methods

Page 64: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Pull Up Constructor Body

class Employee{

private:

string name;

string id;

}

class Manager : public Employee{

private:

int grade;

public:

Manager (string n, string i, int g) {

name = n;

id = i;

grade = g;

}

}

class Employee{

private:

string name;

string id;

public:

Employee(string n , string I ){

name = n;

id = I;

}

}

class Manager : public Employee{

private:

int grade;

public:

Manager (string n, string i, int g) {

Employee (n, i);

grade = g;

}

}

Page 65: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Extract Subclass

When: A class has features that are used only in some instances. Then, create a subclass for that subset of features

Page 66: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Extract Subclass

class JobItem ...

public JobItem (int unitPrice, int quantity,

boolean isLabor, Employee employee) {

_unitPrice = unitPrice;

_quantity = quantity;

_isLabor = isLabor;

_employee = employee; }

public int getTotalPrice() {

return getUnitPrice() * _quantity;

}

public int getUnitPrice(){

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

}

public int getQuantity(){

return _quantity;

}

public Employee getEmployee() {

return _employee;

}

private int _unitPrice;

private int _quantity;

private Employee _employee;

private boolean _isLabor;

class Employee...

public Employee (int rate) {

_rate = rate;

}

public int getRate() {

return _rate;

}

private int _rate;

class JobItem...

protected JobItem (int unitPrice, int quantity,

boolean isLabor) {

_unitPrice = unitPrice;

_quantity = quantity;

protected boolean isLabor() {

return false;

}

public int getUnitPrice(){

return _unitPrice;

}

class LaborItem extends JobItem

public LaborItem (int quantity, Employee employee) {

super (0, quantity, true);

_employee = employee;

}

protected boolean isLabor() {

return true;

}

public int getUnitPrice(){

return _employee.getRate();

}

Page 67: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Extract Superclass

When: several classes with similar features

class Employee { private: string name; string jobTitle; public: string GetName();}

class Student { private: string name; Course course;public: string GetName(); }

class Person { private: string name; public: string GetName();}

class Employee : public Person { private: string jobTitle; }

class Student : public Person { private: Course course; }

Page 68: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Extract Interface

When: several classes have part of their interface in common

Interface: is an empty shell, there are only the signatures (name / params / return type) of the methods. The methods do not contain anything. The interface can't do anything. It's just a pattern.

Page 69: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Extract Interface

double charge(Employee emp, int days) { int base = emp.getRate() * days; if (emp.hasSpecialSkill()) return base * 1.05; else return base;}

interface Billable { public int getRate(); public boolean hasSpecialSkill();}

class Employee implements Billable ...

double charge(Billable emp, int days) { int base = emp.getRate() * days; if (emp.hasSpecialSkill()) return base * 1.05; else return base;}

Page 70: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Collapse Hierarchy

When: A superclass and subclass are not very different

Refactoring Solution: Merge them together

Page 71: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Inheritance with Delegation

When: A subclass uses only part of a superclasses interface or

does not want to inherit data. Refactoring Solution:

Create a field for the superclass, change methods to delegate to the superclass, and remove the subclassing

Page 72: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Replace Inheritance with Delegation

Example:

class MyStack extends Vector {

public void push(Object element) {

insertElementAt(element,0);

}

public Object pop() {

Object result = firstElement();

removeElementAt(0);

return result;

}

class MyStack {

private Vector _vector = new Vector();

public boolean isEmpty() {

return _vector.isEmpty();

}

public void push(Object element) {

_vector.insertElementAt(element,0);

}

public Object pop() {

Object result = _vector.firstElement();

_vector.removeElementAt(0);

return result;

}}

Page 73: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Big Refactoring

Tease Apart Inheritance Split an inheritance hierarchy that is doing two jobs at once

Convert Procedural Design to Objects Separate Domain from Presentation

GUI classes that contain domain logic Extract Hierarchy

Create a hierarchy of classes from a single class where the single class contains many conditional statements

Page 74: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Convert Procedural Design

Take each record type and turn it into a dumb data object with accessors

Take all procedural code and put it into a single class Take each long method and apply Extract Method and the

related factorings to break it down. As you break down the procedures use Move Method to move each one to the appropriate dumb data class

Continue until all behavior is removed from the original class

Page 75: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Convert Procedural Design

Example:

Page 76: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring: Limitations

Tentative list due to lack of experience Database

Database schema must be isolated, or schema evolution must be allowed

Changing Published Interfaces Interfaces where you do not control all of the source code that

uses the interface Must support both old and new interfaces Don't publish interfaces unless you have to

Page 77: Chapter 6: Code Refactoring Omar Meqdadi SE 3860 Lecture 6 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Refactoring: Tools

Smalltalk Refactoring Browser Development environment written in Smalltalk Allows for Smalltalk source code to transform Smalltalk source

code Comments as a first-class part of the language

XRefactory Allows standard refactorings for C++