Software Engineering
Refactoring
CIT2C06 Software Engineering
AY 2006/2007 Oct Semester
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Objectives
Describe
List
the purpose of code refactoring.
code smells.
Apply
code refactoring.
2
TEMASEK INFORMATION TECHNOLOGY SCHOOL
What is Code Refactoring
The
process of changing a software system in such a
way that it:
improves the internal code structure
does not alter external behavior
of code
public class Student {
public String name;
public static void main(String[] args) {
Student s1 = new Student();
s1.name = “Tan Ah Beng”;
Student s2 = new Student();
s2.name = “Lim Ah Seng”;
}
}
Any problems with this code?
3
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Code Refactoring in Action
Use
getter and setter methods
Step 1: Create getter and setter methods
public class Student {
public String name;
public String getName() { return name; }
public void setName(String newName) {
name = newName;
}
public static void main(String[] args) {
Student s1 = new Student();
s1.name = “Tan Ah Beng”;
Student s2 = new Student();
s2.name = “Lim Ah Seng”;
}
}
4
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Code Refactoring in Action
Step
2: Find all clients; replace references with calls.
Do this one at a time
public class Student {
public String name;
public String getName() { return name; }
public String setName(String newName) {
name = newName;
}
public static void main(String[] args) {
Student s1 = new Student();
s1.setName(“Tan Ah Beng”);
Student s2 = new Student();
s2.name = “Lim Ah Seng”;
}
}
5
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Code Refactoring in Action
Step
3: Compile and test
Back to step 2: Replace other references
public class Student {
public String name;
public String getName() { return name; }
public String setName(String newName) {
name = newName;
}
public static void main(String[] args) {
Student s1 = new Student();
s1.setName(“Tan Ah Beng”);
Student s2 = new Student();
s2.setName(“Lim Ah Seng”);
}
}
6
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Code Refactoring in Action
Back
to step 3: Compile and test
Step 4: Once all clients are changed, make the field
private
Step 5: Compile and test one last time
public class Student {
private String name;
public String getName() { return name; }
public String setName(String newName) {
name = newName;
}
public static void main(String[] args) {
Student s1 = new Student();
s1.setName(“Tan Ah Beng”);
Student s2 = new Student();
s2.setName(“Lim Ah Seng”);
}
}
7
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Refactoring
Why
refactor?
Improves the design of software
Makes software easier to understand
Helps you find bugs
Helps you program faster
When
do we refactor?
When you add function
When you need to fix a bug
When you do a code review
8
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Detecting Code Smells
Code
smells are warning signs about problems within
the code
Common smells
Duplicated code
Long methods
Long parameter list
Large classes (in terms of instance variables, methods
and lines)
Data clumps (groups of data items appearing together in
lots of places)
Comments (is it really a bad smell?)
9
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Refactoring Cycle
1.
2.
Start with a working program
While smells remain
a. Choose the worst smell
b. Select a refactoring that will address the smell
c. Apply the refactoring
Remember: the condition for refactoring safely is to
have tests to cover those code we want to refactor
10
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Code Refactoring
Parameterize
Pass
method
Whole Object
Replace
Magic Number with Named Constants
11
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Parameterize Method
Several
methods do similar things but each uses
different values
Replace them with one method that uses a parameter
for the different values
Toy
getTenPercentDiscountedPrice():double
getFivePercentDiscountedPrice():double
Toy
getDiscountedPrice(percent):double
12
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Parameterize Method Example
public class Wizard {
private int willPower;
public int castFireSpell(int damage) {
return damage + (willPower * 1.1);
}
public int castColdSpell(int damage) {
return damage + (willPower * 2.1);
}
public static void main(String[] args) {
……………………………
damage = wizard.castFireSpell(damage);
damage = wizard.castColdSpell(damage);
……………………………
}
}
13
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Parameterize Method in Action
public class Wizard {
private int willPower;
public int castFireSpell(int damage) {
return damage + (willPower * 1.1);
}
public int castColdSpell(int damage) {
return damage + (willPower * 2.1);
}
public int castSpell(int damage, int factor) {
return damage + (willPower * factor);
}
public static void main(String[] args) {
……………………………
damage = wizard.castFireSpell(damage);
damage = wizard.castColdSpell(damage);
……………………………
}
}
14
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Parameterize Method in Action
public class Wizard {
private int willPower;
public int castFireSpell(int damage) {
return damage + (willPower * 1.1);
}
public int castColdSpell(int damage) {
return damage + (willPower * 2.1);
}
public int castSpell(int damage, int factor) {
return damage + (willPower * factor);
}
public static void main(String[] args) {
……………………………
damage = wizard.castSpell(damage,1.1);
damage = wizard.castColdSpell(damage);
……………………………
}
}
15
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Parameterize Method in Action
public class Wizard {
private int willPower;
public int castFireSpell(int damage) {
return damage + (willPower * 1.1);
}
public int castColdSpell(int damage) {
return damage + (willPower * 2.1);
}
public int castSpell(int damage, int factor) {
return damage + (willPower * factor);
}
public static void main(String[] args) {
……………………………
damage = wizard.castSpell(damage,1.1);
damage = wizard.castSpell(damage,2.1);
……………………………
}
}
16
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Pass Whole Object
You
get several values from an object and pass these
values as parameters in a method call
Send the whole object instead
int low = tempRange.getLow();
int high = tempRange.getHigh();
int ave = monitor.computeAverage(low, high);
int ave = monitor.computeAverage(tempRange);
17
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Pass Whole Object Example
class Game {
void throwGrenade(Person rambo, Grenade g) {
int xPos = rambo.getX();
int yPos = rambo.getY();
if (g.isWithinRange(xPos, yPos))
rambo.addDamage(10);
}
}
class Grenade {
boolean isWithinRange(int xPos, int yPos) {
if ((xPos >= gx) && (xPos <= gx + 25) &&
(yPos >= yx) && (yPos <= yx + 25))
return true;
else
return false;
}
}
18
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Pass Whole Object in Action
class Game {
void throwGrenade(Person rambo, Grenade g) {
int xPos = rambo.getX();
int yPos = rambo.getY();
if (g.isWithinRange(rambo, xPos, yPos))
rambo.addDamage(10);
}
}
class Grenade {
boolean isWithinRange(Person r, int xPos, int yPos) {
if ((xPos >= gx) && (xPos <= gx + 25) &&
(yPos >= yx) && (yPos <= yx + 25))
return true;
else
return false;
}
}
19
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Pass Whole Object in Action
class Game {
void throwGrenade(Person rambo, Grenade g) {
int xPos = rambo.getX();
int yPos = rambo.getY();
if (g.isWithinRange(rambo, xPos, yPos))
rambo.addDamage(10);
}
}
class Grenade {
boolean isWithinRange(Person r, int xPos, int yPos) {
if ((r.getX() >= gx) && (r.getX() <= gx + 25) &&
(r.getY() >= yx) && (r.getY() <= yx + 25))
return true;
else
return false;
}
}
20
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Pass Whole Object In Action
class Game {
void throwGrenade(Person rambo, Grenade g) {
int xPos = rambo.getX();
int yPos = rambo.getY();
if (g.isWithinRange(rambo, xPos, yPos))
rambo.addDamage(10);
}
}
class Grenade {
boolean isWithinRange(Person r, int xPos, int yPos) {
if ((r.getX() >= gx) && (r.getX() <= gx + 25) &&
(r.getY() >= yx) && (r.getY() <= yx + 25))
return true;
else
return false;
}
}
21
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Replace Magic Number with Named Constant
In
your code, you use literals directly
Instead of using the literals directly, create a constant
giving it an appropriate name, and use the constant
instead
double parcelAmount (double wt) {
return 0.50 * wt;
}
private final static double AIRMAIL_RATE = 0.50;
double parcelAmount (double wt) {
return AIRMAIL_RATE * wt;
}
22
TEMASEK INFORMATION TECHNOLOGY SCHOOL
Recap
What
is refactoring and why is it important?
Describe 3 code smells.
Give examples on the application of the following
refactorings:
Parameterize Method
Pass Whole Object
Replace Magic Number with Named Constant
23