SE 333/433 Software Testing & Quality Assurance
Refactoring
1
Last Week
2
Another System Model (Data-Bases)
Program (in Java)
Model transformation
Refactoring
System Model (in UML)
Reverse engineering
Another Program (Java)
Model space
Source code space
3
Forward engineering
Design to code Refactoring
4
Class and Attribute
float
float
5
float float
float float
Operations
6
Visibility
7
Class scope
8
Unidirectional Association
11
Advertiser Account
public class Advertiser { private Account account;
} }
public Advertiser() {
account = new Account();
}
public Account getAccount() {
return account;
9
Association names & role defaults
10
public class Advertiser { /* account is initialized
public class Account {
/* owner is initialized
} }
private Account account; public Advertiser() {
* never modified. */
private Advertiser owner;
public Account(owner:Advertiser) {
Bidirectional Association
Advertiser
Account
* in the constructor and never
* modified. */
* in the constructor and
account = new Account(this);
this.owner = owner; }
}
public Account getAccount() {
public Advertiser getOwner() { return owner;
return account;
} }
11
11
Multiplicity
12
Aggregation and Composition
13
Generalization
14
Realization
15
Abstraction
16
Association classes
17
Associations, Visibility & Scope
18
?
public int getX() { return _x;
}
Example
public class Point { private int _x; private int _y;
public class Polygon { private Point corners[];
}
public Point(int x, int y) { _x=x; _y=y;
}
public int getY() { return _y;
}
Polygon(int[][] points) { }
19
Polygon(int[][] points)
throws IllegalArgumentException {
if (points.length< 3) {throw new IllegalArgumentException( “Not enough corners “);}}else {corners=new Point[points.length]; for (int i=0; i
class PizzaDelivery {
//
int getRating() {
return numberOfLateDeliveries > 5 ? 2 : 1;
Inline Method
When a method body is more obvious than the method itself.
Eliminates code smell : Dead code (unused class, method, field etc.
class PizzaDelivery
28
Eliminates code smell : comments
void renderBanner() {
if ((platform.toUpperCase().indexOf(MAC) > 1) && (browser.toUpperCase().indexOf(IE) > 1)
&& wasInitialized() && resize > 0 ) { // do something } }
Extract Variable
void renderBanner() {
final boolean isMacOs = platform.toUpperCase().indexOf(MAC) > 1;
final boolean isIE = browser.toUpperCase().indexOf(IE) > 1; final boolean wasResized = resize > 0;
if (isMacOs && isIE && wasInitialized() && wasResized) { // do something }
}
29
double basePrice = order.basePrice(); return basePrice > 1000;
}
Inline Temp
You have a temporary variable thats assigned the result of a simple expression and nothing more.
boolean hasDiscount(Order order) {
boolean hasDiscount(Order order) { return order.basePrice() > 1000;
}
30
if (basePrice > 1000) { return basePrice * 0.95; }
} else {
else {
return basePrice * 0.98;
return basePrice() * 0.98; }
} }
}
double basePrice() {
Replace Temp with Query
If a temporary variable hold the result of an expression.
Extract the expression into a method.
Eliminates code smell : Long method, duplicate code
double calculateTotal() {
double calculateTotal() {
double basePrice = quantity * itemPrice;
if (basePrice() > 1000) { return basePrice() * 0.95;
return quantity * itemPrice; } 31
Inline Class
Refactoring Techniques
Moving Features between Objects Move Method
Move Field
Extract Class
32
Move Method
If a method on one class uses (or is used by) another class more than the class on which its defined, move it to the other class.
Eliminates code smell : Shotgun Surgery, Feature Envy, Data Class
public class Student
{
public boolean isTaking(Course course)
{
return (course.getStudents().contains(this));
}
}
public class Course
{ public boolean isTaking(Student student) private List students;
public List getStudents()
{
return students;
}
}
public class Student {
}
public class Course {
private List students;
{
return students.contains(student); }
}
33
Move Method
34
Move Field
35
public class Customer
{
private String name;
private String workPhoneAreaCode; private String workPhoneNumber;
public class Customer
{
private String name; private Phone workPhone; }
}
public class Phone
{
private String areaCode; private String number;
Extract Class
Break one class into two, e.g. Having the phone details as part of the Customer class is not a realistic OO model.
Eliminate code smell : Large Class, Duplicate Code, ..
}
36
Extract Class
37
Inline Class
Eliminate code smell : Shotgun Surgery, lazy class, oldbagage/deadcode ..
38
Refactoring Techniques
Generalization
Pull Up Field
Pull Up Method
Push Down Method
Push Down Field
Extract Subclass
Extract Superclass
Replace Inheritance with Delegation Replace Delegation with Inheritance
39
Eliminate code smell : Duplicate Code
Pull Up Field
40
Eliminate code smell : Duplicate Code
Pull Up Method
41
Push Down Method
42
Push Down Field
43
Extract Subclass
When a class has features (attributes and methods) that would only be useful in specialized instances, we can create a specialization of that class and give it those features.
This makes the original class less specialized (i.e., more abstract), and good design is about binding to abstractions wherever possible.
44
Eliminate code smell : Large Class
public class Person{
public class Person
{
protected String name; }
private String name;
private String jobTitle; }{
Extract Subclass
public class Employee extends Person
private String jobTitle; }
45
Extract Subclass
46
Extract Superclass
When you find two or more classes that share common features, consider abstracting those shared features into a superclass.
This makes it easier to bind clients to an abstraction, and removes duplicate code from the original classes.
47
private String name; private Course course; }
public class Student extends Person {
private Course course;
}
Extract Superclass
public class Employee
{
private String name;
private String jobTitle; }{
public class Student private String jobTitle; {}
public abstract class Person {
protected String name;
}
public class Employee extends Person
48
Eliminate code smell : Duplicate Code
Extract Superclass
49
Replace Inheritance with Delegation
50
Replace Delegation with Inheritance
51
Refactoring Techniques
Simplifying Conditional Expressions
Decompose Conditional
Consolidate Conditional Expression
Replace Nested Conditional with Guard Clauses Replace Conditional with Polymorphism
52
Eliminates : long method
} else {
charge = quantity * summerRate;
}
else {
}
charge = winterCharge(quantity); }
Decompose Conditional
if (date.before(SUMMER_START) || date.after(SUMMER_END)) { charge = quantity * winterRate + winterServiceCharge;
if (isSummer(date)) {
charge = summerCharge(quantity);
53
double disabilityAmount() { if (seniority < 2) {double disabilityAmount() {if (isNotEligableForDisability()) {return 0; }return 0; }if (monthsDisabled > 12) { return 0; }
if (isPartTime) { return 0;
}
// Compute the disability amount. // }
// Compute the disability amount. //
}
Consolidate Conditional Expression
Eliminates : Duplicate Code
54
public double getPayAmount() { double result;
if (isDead){
result = deadAmount(); }
else {
if (isSeparated){
public double getPayAmount() { if (isDead){
result = separatedAmount(); } else {
if (isSeparated){
return separatedAmount(); }
if (isRetired){
return retiredAmount();
}
return normalPayAmount(); }
if (isRetired){
result = retiredAmount(); }
else{
result = normalPayAmount();
}
55
}
}
}
return result;
Replace Nested Conditional with Guard Clauses
return deadAmount(); }
class Bird { //
class European extends Bird { double getSpeed() {
return getBaseSpeed();
double getSpeed() { switch (type) {
} }
Replace Conditional with Polymorphism
Eliminates : Switch Statment
abstract class Bird { //
case EUROPEAN: return getBaseSpeed();
case AFRICAN: return getBaseSpeed() getLoadFactor() * numberOfCoconuts;
case NORWEGIAN_BLUE:
return (isNailed) ? 0 : getBaseSpeed(voltage);
}
class African extends Bird { double getSpeed() {
throw new RuntimeException(Should be unreachable); }
}
class NorwegianBlue extends Bird { double getSpeed() {
}
return (isNailed) ? 0 : getBaseSpeed(voltage); }
abstract double getSpeed(); }
return getBaseSpeed() getLoadFactor() * numberOfCoconuts; }
} // Somewhere in client code speed = bird.getSpeed();
56
Summary
57
Site : http://refactoring.com
References
Book : Improving the Design of Existing Code (by Martin Fowler
58
Eclipse examples
59
Reviews
There are no reviews yet.