Lec 5 - Refactoring
Lec 5 - Refactoring
What is refactoring?
Why should we refactor?
When should we refactor?
Refactoring Techniques
Activities in Refactoring process
2
What is refactoring?
Refactoring is a software transformation (re-organization) that:
preserves the external behavior of the software;
improves the internal structure of the software.
Refactoring does not modify the software’s functionalities.
3
Why should we refactor? - Problem
Developers continuously modify, enhance and adapt software.
As software evolves and strays away from its original design, three
things happen:
Decreased understandability due to
Increased complexity of code
Out-of-date documentation
Code not conforming to standards
Decreased reliability
Increased maintenance cost
4
Why should we refactor? - Resolution
Software refactoring is stated as the modifications of software (source
code + documentation) to make it:
➢ easier to understand;
➢ easier to change (faster to program);
➢ maintained with reduced cost;
➢ less susceptible to faults when changes are made to it.
5
When should we refactor?
Refactor when adding new features or functions
Especially if feature is difficult to integrate with the existing code.
Refactor during bug fixing
If a bug is very hard to trace, refactor first to make the code more
understandable, so that you can understand better where the bug is located.
Refactor during code reviews.
Don't set aside time for refactoring, include it in your normal activities
6
Movie Rental
7
Movie Rental Example – Sample output
Rental Record for this customer is:
Fast & Furious 3.5
The matrix 6
Star Wars 3
Twilight: Breaking Dawn 6
Amount owed is: 18.5
You earned 5 frequent renter points
8
Starting Class Diagram
9
public class Movie { Class Movie
public static final int CHILDRENS = 2;
public static final int REGULAR = 0;
public static final int NEW_RELEASE = 1;
private String _title;
private int _priceCode;
15
A. Code Refactoring – (de)composing methods
1. Extract Method
This Course
2. Inline Method
3. Introduce Explaining Variable
4. Inline Temp
5. Replace Temp With Query
6. Split Temporary Variable
Self Study
7. Remove Assignments to Parameter
8. Replace Method With Method Object
9. Substitute Algorithm
16
A. Code Refactoring – (de)composing methods
1. Extract method
When you have a fragment of
code that can be grouped
together, turn it into a method
with a name that explains the
purpose of the method.
➢ Reason: This improves clarity,
and removes redundancy
18
A. Code Refactoring – (de)composing methods
1. Extract method - example
//Refactored code: Extracting the Amount Calculation
private int amountFor(Rental each) {
int thisAmount = 0;
switch (each.getMovie().getPriceCode()) {
case Movie.REGULAR:
thisAmount += 2;
if (each.getDaysRented() > 2)
thisAmount += (each.getDaysRented() - 2) * 1.5;
break;
case Movie.NEW_RELEASE:
thisAmount += each.getDaysRented() * 3;
break;
case Movie.CHILDRENS:
thisAmount += 1.5;
if (each.getDaysRented() > 3)
thisAmount += (each.getDaysRented() - 3) * 1.5;
break;
}
return thisAmount;
} 19
A. Code Refactoring – (de)composing methods
1. Extract method - example
//statement ( ) after extraction
public String statement() {
......
while (rentals.hasMoreElements()) {
double thisAmount = 0;
Rental each = (Rental) rentals.nextElement();
thisAmount = amountFor(each);
// add frequent renter points
..........
// add bonus for a two day new release rental
…......
//show figures for this rental
…….
return result; }
} 21
A. Code Refactoring – (de)composing methods
2. Inline method
When a method’s body is just as clear as its name, put the method’s
body into the body of its caller and remove the method.
➢ Reason: To remove too much indirection and delegation
Example
int amountFor(Rental aRental){
.... int amountFor(Rental aRental){
if(moreThanTwoDaysRented(aRental)) ....
result+= .... if(aRental.getDaysRented>2)
} result+= ....
}
boolean moreThanTwoDaysRented(Rental r){
return r.getDaysRented> 2;
}
22
A. Code Refactoring – (de)composing methods
3. Introduce Explaining Variable
When you have a complex expression, put the result of (or parts of)
the expression in a temporary variable with a name that explains the
purpose.
➢ Reason: Breaking down complex expressions for clarity
Example
if (each.getMovie().getPriceCode() == Movie.NEW_RELEASE &&
each.getMovie().getTitle().indexOf(“furious”) > -1 &&
each.getDaysRented() > 1)
{ frequentRenterPoints ++; }
24
B. Code Refactoring – Moving Features between Objects
1. Move method
When a method is used by or using more features of another class than
the class it is defined on, create a new method with a similar body in
the class it uses most. Either turn the old method into a simple
delegation or remove it altogether.
➢ Reason: Essence of refactoring
25
B. Code Refactoring – Moving Features between Objects
1. Move method - example
class Customer {
private double amountFor(Rental aRental) {
double result = 0; Is this method in the right place?
switch (aRental.getMovie().getPriceCode()) {
case Movie.REGULAR:
result += 2;
if (aRental.getDaysRented() > 2)
result += (aRental.getDaysRented() - 2) * 1.5;
break;
case Movie.NEW_RELEASE:
result += aRental.getDaysRented() * 3;
break;
case Movie.CHILDRENS:
result += 1.5;
if (aRental.getDaysRented() > 3)
result += (aRental.getDaysRented() - 3) * 1.5;
break;
}
return result;
}
} 26
B. Code Refactoring – Moving Features between Objects
1. Move method
Steps for Move method:
Declare method in target class.
Copy and fit code.
Set up a reference from the source object to the target.
Turn the original method into a delegating method
➢ amountOf(Rental each) {return each.charge()}
Find all callers of the method and adjust them to call method on target.
Remove original method.
27
B. Code Refactoring – Moving Features between Objects
1. Move method - example
class Rental {
double getCharge( ) {
double result = 0;
switch (getMovie().getPriceCode()) {
case Movie.REGULAR:
result += 2;
if (getDaysRented() > 2)
result += (getDaysRented() - 2) * 1.5;
break;
case Movie.NEW_RELEASE:
result +=getDaysRented() * 3;
break;
case Movie.CHILDRENS:
result += 1.5;
if (getDaysRented() > 3)
result += (getDaysRented() - 3) * 1.5;
break;
}
return result;
}
} 28
B. Code Refactoring – Moving Features between Objects
1. Move method - example
30
C. Code Refactoring – Organizing Data
1. Encapsulate Fields
When there is a public field, make it private and provide accessors.
➢ Reason: Encapsulating state increases modularity, and facilitates code
reuse and maintenance.
➢ When the state of an object is represented as a collection of private variables, the
internal representation can be changed without modifying the external interface.
31
E. Code Refactoring – Dealing with Generalization
1. Push down method / field
2. Pull up method / field
This Course
3. Extract subclass / superclass
4. Form template method
5. Collapse hierarchy
Self Study
6. Replace inheritance with delegation (and vice versa)
32
E. Code Refactoring – Dealing with Generalization
1. Push down method/field
When behavior on a superclass is relevant only for some of its
subclasses, move it to those subclasses.
Employee Employee
getQuota ( )
Salesman Engineer
33
E. Code Refactoring – Dealing with Generalization
2. Pull up method/ field (inverse of push down)
Simple variant: look for methods with same name in subclasses that do
not appear in superclass.
More complex variant: do not look at the name but at the behavior of
the method.
If the method that is being pulled up already exists in the superclass as
an abstract method, make it concrete with the common behavior
34
E. Code Refactoring – Dealing with Generalization
3. Extract subclass/ superclass
When two (or more) classes have common attributes and methods,
extract these common features to a new superclass.
35
E. Code Refactoring – Dealing with Generalization
3. Extract subclass/ superclass
When a class has methods/ fields which are used only in certain cases,
extract the rare case into it’s own class and extend it to the original class
Shape
Shape calculateArea ( )
getCircleRadius ( )
getTriangleHeight( )
calculateArea ( )
Circle Triangle
getRadius ( ) getHeight ( )
36
E. Code Refactoring – Dealing with Generalization
4. Form Template Class
You have two methods in subclasses that perform similar steps in the
same order, yet the steps are different.
➢ Get the steps into methods with the same signature, so that the original
methods become the same. Then you can pull them up.
37
F. Code Refactoring – Simplifying method calls
1. Rename method This Course
2. Introduce parameter object
3. Add parameter
4. Remove parameter
Self Study
5. Parameterize method
6. Replace parameter with method
7. .......
38
F. Code Refactoring – Simplifying method calls
1. Rename method
When the name of a method doesn’t explain what the method does
(i.e., was poorly named from the very beginning, or was well named at
first but as its functionality grew, the method name stopped being a
good descriptor). Then rename it.
Example
39
F. Code Refactoring – Simplifying method calls
2. Introduce parameter object
When identical groups of parameters are encountered in multiple
methods, replace these parameters with an object and use that object
as parameter instead.
Example
public double amountInvoicedIn (Date start, Date end) public double amountInvoicedIn (DateRange dt)
{...} {...}
public double amountReceivedIn (Date start, Date end) public double amountReceivedIn (DateRange dt)
{...} {...}
public double amountOverdueIn (Date start, Date end) public double amountOverdueIn (DateRange dt)
{...} {...}
} }
40
Refactoring Tools (FYI)
Available for all major programming languages
(and OO programming languages in particular)
Java : IntelliJ IDEA, Eclipse, NetBeans, JDeveloper, …
JavaScript : WebStorm, Eclipse, …
C++ : VisualStudio, Eclipse, …
ObjectiveC and SWIFT : XCode
.NET : VisualStudio
Smalltalk, PHP, Ruby, Python, C#, Delphi, …
41
Activities in Refactoring Process
1. Identify what to refactor (code smell concept; next lecture)
2. Determine which refactorings to apply.
- For large sets of refactorings, tool support is needed to identify a
feasible subset of refactorings.
- The following two techniques can be used to analyze a set of
refactorings to select a feasible subset:
➢ Critical pair analysis
Given a set of refactorings, analyze each pair for conflicts. A pair is said
to be conflicting if both of them cannot be applied together.
➢ Sequential dependency analysis
- In order to apply a refactoring, one or more refactorings must be
applied before. 42
Activities in Refactoring Process
3. Ensure that refactoring preserves the software’s behavior.
Ideally, the input/output behavior of a program after refactoring is
the same as the behavior before refactoring.
This could be validated by testing the software before and after
applying refactorings and ensuring that the sequence(s) of method
calls are preserved in the refactored program
43
Activities in Refactoring Process
5. Evaluate the impacts of the refactorings.
Refactoring techniques are highly specialized, with one technique
improving a small number of quality attributes.
Software metrics can be used to quantify the quality of software
after being refactored. Two metrics are considered:
➢ Cohesion:This metric is used to represent the strength of
togetherness in the same module.
➢ Coupling:
This metric is used to represent the strength of
dependency between separate modules.
44
Exercises
dependency between separate modules strength of
togetherness in
Coupling is a software metric used to...... while cohesion is used to..... the same module
......, ........ are two techniques that can be used to analyze a set of
refactorings to select a feasible subset.
Refactoring requires changing the external behavior of the software by
adding new functionalities. (T/F)
Replace each statement with the proper refactoring pattern: extract sub/super
class
When two (or more) classes have common attributes and methods.
When you have methods with same name in subclasses that do not
appear in superclass. extract super class // form template method
45
Midterm exam includes the following lectures:
➢ Lecture 1: Software Maintenance Fundamentals
➢ Lecture 2: Software Maintenance Process and Models
➢ Lecture 3: Software Configuration Management
Midterm Total Marks: ( ASU: 15 marks → UEL :100 marks)
Questions might include: Replace with key terms, Complete, T/F
(correct false ones)
Answer in the exam sheet.
46