0% found this document useful (0 votes)
47 views46 pages

Lec 5 - Refactoring

The document discusses refactoring code. It begins by defining refactoring as modifying code without changing functionality to improve structure and understandability. Reasons for refactoring include decreasing complexity, improving reliability and reducing costs. Techniques discussed include extracting methods to group related code fragments and inlining methods when the method body is clearer than the name. The document provides examples of refactoring code for a movie rental system.

Uploaded by

Salah Ashraf
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
47 views46 pages

Lec 5 - Refactoring

The document discusses refactoring code. It begins by defining refactoring as modifying code without changing functionality to improve structure and understandability. Reasons for refactoring include decreasing complexity, improving reliability and reducing costs. Techniques discussed include extracting methods to group related code fragments and inlining methods when the method body is clearer than the name. The document provides examples of refactoring code for a movie rental system.

Uploaded by

Salah Ashraf
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 46

Agenda

 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.

It is a disciplined way to clean up code that minimizes the chances of


introducing bugs.

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;

public Movie(String title, int priceCode) {


_title = title;
_priceCode = priceCode;
}
public int getPriceCode() {
return _priceCode; }
public void setPriceCode(int arg) {
_priceCode = arg; }
public String getTitle () {
return _title; };
}
10
Class Rental
class Rental {
private Movie _movie;
private int _daysRented;
public Rental(Movie movie, int daysRented) {
_movie = movie;
_daysRented = daysRented;
}
public int getDaysRented() {
return _daysRented;
}
public Movie getMovie() {
return _movie; }
}
11
Class Customer
class Customer {
private String _name;
private Vector _rentals = new Vector();
public Customer (String name) {
_name = name;
}
public void addRental(Rental arg) {
_rentals.addElement(arg);
}
public String getName () {
return _name;
}
public String statement() // see next slide 12
public String statement() { Customer.statement () - Part 1
double totalAmount = 0;
int frequentRenterPoints = 0;
Enumeration rentals = _rentals.elements();
String result = "Rental Record for " + getName() + "\n";
while (rentals.hasMoreElements()) {
double thisAmount = 0;
Rental each = (Rental) rentals.nextElement();
//determine amounts for each line
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;
} //continues on next slide 13
Customer.statement () - Part 2
// add frequent renter points
frequentRenterPoints ++;
// add bonus for a two day new release rental
if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&
each.getDaysRented() > 1) frequentRenterPoints ++;
//show figures for this rental
result += "\t" + each.getMovie().getTitle()+ "\t" + String.valueOf(thisAmount) + "\n";
totalAmount += thisAmount;
//add footer lines
result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter
points";
return result;
}
14
Code Refactoring Techniques
A. Composing/Decomposing Methods
B. Moving Features between Objects
C. Organizing data
D. Simplifying conditional expressions.
E. Dealing with generalization.
F. Simplifying method calls

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

Example for Candidate Extraction 17


A. Code Refactoring – (de)composing methods
1. Extract method
Steps for extract method
 Create method named after intention of code.
 Copy extracted code.
 Look for local variables and parameters:
➢ turn into parameter.
➢ turn into return value.
➢ declare within method
 Replace code fragment with call to new method.

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 ++; }

boolean isNewRelease= (each.getMovie().getPriceCode() == Movie.NEW_RELEASE);


boolean isActionMovie = each.getMovie().getTitle().indexOf(“furious”) > -1 ;
boolean isRented = each.getDaysRented() > 1;

if (isNewRelease && isActionMovie && isRented)


{frequentRenterPoints ++; } 23
B. Code Refactoring – Moving Features between Objects
1. Move Method
This Course
2. Extract Class
3. Move Field
4. Inline Class
5. Hide Delegate Self Study

6. Remove Middle Man


7. Introduce Foreign Method
8. Introduce Local Extension

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

class Customer { class Customer {


public String statement() { public String statement() {
...... ......
while (rentals.hasMoreElements()) { while (rentals.hasMoreElements()) {
double thisAmount = 0; double thisAmount = 0;
Rental each = (Rental) rentals.nextElement(); Rental each = (Rental) rentals.nextElement();
thisAmount = amountFor(each); thisAmount = each.getCharge( );
...... …….
return result; return result;
} }
} }
29
C. Code Refactoring – Organizing Data
1. Encapsulate field This Course

2. Replace data value with object


3. Change value to reference
4. Change reference to value
Self Study
5. Replace array with object
6. Duplicate observed data
7. .......

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.

 Example private String title;


public String movieTitle; public String getTitle() {
return this.title; }
public void setTitle(String s) {
this.title = s; }

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

Salesman Engineer getQuota ( )

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

class Customer{ class Customer{

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

4. Apply the refactorings to the chosen entities.

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

 When you have a complex expression inside a condition or in an


assignment operation. introduce explaining variable

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

You might also like