Download presentation
Presentation is loading. Please wait.
Published byHilary Garrett Modified over 9 years ago
1
Refactoring Improving code after it has been written
2
The Problem: Design is not always optimal “Improving the design after it has been written” “Improving the design after it has been written” Code deteriorates over time with changes Code deteriorates over time with changes Make many small changes Make many small changes Test after each change Test after each change Radical change through cumulative effect Radical change through cumulative effect
3
An Example Write Software for Movie Rentals
4
The class Movie public 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;} }
5
The class Rental public class Rental{ private Movie –movie; public Rental(Movie movie, int daysRented){ _movie = movie; _daysRented = daysRented;} public int getDaysRented(){return _daysRented;} public Movie getMovie(){return _movie;} }
6
The class Customer public 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 void statement(); //see below }
7
Class Diagram of Rental Program Customer Rental Movie statement() int: daysRented int: priceCode 1 * 1 *
8
Sequence Diagram
9
Method statement (1 of 3) public String statement(){ 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();
10
Method statement (2 of 3) 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; } //switch
11
Method statement (3 of 3) frequentRenterPoints++; if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&(each.getDaysRented()>1) frequentRenterPoints++; result += “\t”+each.getMovie().getTitle()+”\t”+ String.valueOf(thisAmount)+”\n”; totalAmount += thisAmount; result += “AmountOwed is “ + String.valueOf(totalAmount) +”\n”; result += “You earned “ + String.valueOf( frequentRenterPoints)+”frequent renter points”; return result; }
12
What is wrong? Program works Program works Method statement is way too long Method statement is way too long Decompose it into smaller pieces Decompose it into smaller pieces So find a logical piece of code So find a logical piece of code Try the switch statement Try the switch statement
13
Write method amountFor(Rental each); 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.NEWRELEASE: thisAmount += each.getDaysRented()*3; break; case Movie.CHILDRENS: thisAmount += 1.5; if (each.getDaysRented()-3)*1.5; break;} return thisamount; } //switch MoveMethod
14
public String statement(){ 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(); thisAmount = amountFor(each); frequentRenterPoints++; if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&(each.getDaysRented()>1) frequentRenterPoints++; result += “\t”+each.getMovie().getTitle()+”\t”+ String.valueOf(thisAmount)+”\n”; totalAmount += thisAmount; result += “AmountOwed is “ + String.valueOf(totalAmount) +”\n”; result += “You earned “ + String.valueOf( frequentRenterPoints)+”frequent renter points”; return result; }
15
Problem Tests reveal that return type is double, not int
16
Write it again private double amountFor(Rental aRental){ double result = 0; switch (aRental.getMovie().getPriceCode()){ case Movie.REGULAR: result += 2; if (aRental.getDaysRented()>2) result += (each.getDaysRented()-2)*1.5; break; case Movie.NEWRELEASE: result += aRental.getDaysRented()*3; break; case Movie.CHILDRENS: result += 1.5; if (aRental.getDaysRented()-3)*1.5; break; } return result; } //switch
17
Mistake was found Testing is crucial at each refactoring step
18
Examine new amountFor() It doesn’t use any customer data! It doesn’t use any customer data! Method is in the wrong place. Method is in the wrong place. Put it in rental Put it in rental It gets a new name: getCharge() It gets a new name: getCharge()
19
class Rental … public double getCharge() { double result = 0; switch (getMovie().getPriceCode()){ case Movie.REGULAR: result += 2; if (getDaysRented()>2) result += (getDaysRented()-2)*1.5; break; case Movie.NEWRELEASE: result += getDaysRented()*3; break; case Movie.CHILDRENS: result += 1.5; if (getDaysRented()-3)*1.5; break; } return result; } MoveMethod
20
class Customer… Private double amountFor(Rental aRental){ return aRental.getCharge(); }
21
Fix up program Have to find all references for amountFor and change to getCharge()
22
class customer… public String statement(){ 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(); thisAmount = amountFor(each); frequentRenterPoints++; if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&(each.getDaysRented()>1) frequentRenterPoints++; result += “\t”+each.getMovie().getTitle()+”\t”+ String.valueOf(thisAmount)+”\n”; totalAmount += thisAmount;} result += “AmountOwed is “ + String.valueOf(totalAmount) +”\n”; result += “You earned “ + String.valueOf( frequentRenterPoints)+”frequent renter points”; return result; }
23
becomes
24
class customer… public String statement(){ 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(); thisAmount = each.getCharge(); frequentRenterPoints++; if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&(each.getDaysRented()>1) frequentRenterPoints++; result += “\t”+each.getMovie().getTitle()+”\t”+ String.valueOf(thisAmount)+”\n”; totalAmount += thisAmount;} result += “AmountOwed is “ + String.valueOf(totalAmount) +”\n”; result += “You earned “ + String.valueOf( frequentRenterPoints)+”frequent renter points”; return result; }
25
Now notice thisAmount is redundant
26
class customer… public String statement(){ 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(); frequentRenterPoints++; if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&(each.getDaysRented()>1) frequentRenterPoints++; result += “\t”+each.getMovie().getTitle()+”\t”+ String.valueOf(each.getCharge())+”\n”; totalAmount += each.getCharge();} result += “AmountOwed is “ + String.valueOf(totalAmount) +”\n”; result += “You earned “ + String.valueOf( frequentRenterPoints)+”frequent renter points”; return result; } Replace Temp with Query
27
Now extract code for Frequent Renter Points
28
public String statement(){ double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for”+getname()+”\n”; while(rentals.hasMoreElements(){ Rental each = (Rental)rentals.nextElement(); frequentRenterPoints++; if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&(each.getDaysRented()>1) frequentRenterPoints++; result += “\t”+each.getMovie().getTitle()+”\t”+ String.valueOf(each.getCharge())+”\n”; totalAmount += each.getCharge();} result += “AmountOwed is “ + String.valueOf(totalAmount) +”\n”; result += “You earned “ + String.valueOf( frequentRenterPoints)+”frequent renter points”; return result; } Extract Method
29
And put in in Rental:
30
class Customer… public String statement(){ 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(); frequentRenterPoints += each.getFrequentRenterPoints(); result += “\t”+each.getMovie().getTitle()+”\t”+ String.valueOf(each.getCharge())+”\n”; totalAmount += each.getCharge();} result += “AmountOwed is “ + String.valueOf(totalAmount) +”\n”; result += “You earned “ + String.valueOf( frequentRenterPoints)+”frequent renter points”; return result; }
31
class Rental… int getFrequentRenterPoints(){ if ((getMovie().getPriceCode() == Movie.NEW_RELEASE) &&(getDaysRented()>1) return 2; else return 1; }
32
RemoveTemp Variables Temps encourage complexity Temps encourage complexity Here: totalAmount and frequentRenterPoints Here: totalAmount and frequentRenterPoints Replace totalAmount with Customer method getTotalCharge() Replace totalAmount with Customer method getTotalCharge()
33
class Customer… public String statement(){ int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for”+getname()+”\n”; while(rentals.hasMoreElements(){ Rental each = (Rental)rentals.nextElement(); frequentRenterPoints += each.getFrequentRenterPoints(); result += “\t”+each.getMovie().getTitle()+”\t”+ String.valueOf(each.getCharge())+”\n”; totalAmount += each.getCharge();} result += “AmountOwed is “ + String.valueOf(getTotalCharge()) +”\n”; result += “You earned “ + String.valueOf( frequentRenterPoints)+”frequent renter points”; return result; } Replace Temp with Query
34
class customer… private double getTotalCharge(){ double result = 0; Enumeration rentals = _rentals.elements(); while (rentals.hasMoreElements()){ Rental each = (Rental)rentals.nextElement(); result += each.getCharge(); } return result; }
35
Now do the same for frequentRenterPoints
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.