Refactoring - PowerPoint PPT Presentation

1 / 26
About This Presentation
Title:

Refactoring

Description:

{ case Movie.REGULAR: thisAmount = 2; if (each.getDaysRented() 2) ... Eclipse. Others on web site. Next Time. How do we test this stuff? ... – PowerPoint PPT presentation

Number of Views:101
Avg rating:3.0/5.0
Slides: 27
Provided by: Robert9
Category:

less

Transcript and Presenter's Notes

Title: Refactoring


1
Refactoring
  • CS4320
  • Fall 2005

2
Definition
The process of changing a software system in such
a way that it does not alter the external
behavior of the code, yet improves its internal
structure. It is a disciplined way to clean up
code that minimizes the chances of introducing
bugs. Improving the design after its been
written.
3
Video Store Example
4
public class Movie public static final int
CHILDRENS 2 public static final int REGULAR
0 public static final int NEW_RELEASE
1   public 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
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

6
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
7
public String statement()   double
totalAmount 0 int frequentRenterPoints
0 Enumeration rentals _rentals.elements()
String result "Rental Record for "
getName() "\n"   while (rentals.hasMoreElem
ents()) 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() gt 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() gt 3) thisAmount
(each.getDaysRented() - 3) 1.5
break    
8
// Add frequent renter points
frequentRenterPoints   // Add bonus for
a two-day, new-release rental if
((each.getMovie().getPriceCode()
Movie.NEW_RELEASE) each.getDaysRented()
gt 1) frequentRenterPoints // Show
figures for this rental result "\t"
each.getMovie().getTitle() "\t"
Sting.valueOf(thisAmount) "\n"
totalAmount thisAmount   // Add
footer lines result "Amount owed is "
String.valueOf(totalAmount) "\n" result
"You earned " String.valueOf(frequentRenterPoint
s) " frequent renter points" return
result
9
Video Store Example
10
Impressions of this code?
Not really OO. Poor organization. Statement
routine supiciously long. What if we had to
change, I.e. put statement in HTML? What if
charging rules change? What if we add new rental
category?
11
First step in refactoring
PREPARE TESTS We will look at this in Extreme
Programming And JUnit. Always refactor in small
steps and test.
12
Principles
  • Abstraction (Information Hiding)
  • Flexibility
  • Clarity
  • Irredundancy

13
Refactoring 1 Extract method.
private double amountFor(Rental each)
double thisAmount 0 switch
(each.getMovie().getPriceCode()) case
Movie.REGULAR thisAmount 2
if (each.getDaysRented() gt 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(
) gt 3) thisAmount (each.getDaysRented
() - 3) 1.5 break   return
thisAmount
switch (each.getMovie().getPriceCode())
case Movie.REGULAR thisAmount 2
if (each.getDaysRented() gt 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() gt 3) thisAmount
(each.getDaysRented() - 3) 1.5
break
thisAmount amountFor(each)
14
Refactoring 2 Renaming Variables
private double amountFor(Rental aRental)
double result 0   switch (aRental.getMovie().
getPriceCode()) case Movie.REGULAR
result 2 if (aRental.getDaysRented() gt
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() gt 3) result
(aRental.getDaysRented() - 3) 1.5
break   return result
15
Refactoring 3 Move Method
//add to rental class double getCharge()
double result 0   switch
(getMovie().getPriceCode()) case
Movie.REGULAR result 2 if
(getDaysRented() gt 2) result
(getDaysRented() - 2) 1.5 break
case Movie.NEW_RELEASE result
getDaysRented() 3 break case
Movie.CHILDRENS result 1.5
if (getDaysRented() gt 3) result
(getDaysRented() - 3) 1.5 break
return result
//and adjust customer class private double
amountFor(Rental aRental) return
aRental.getCharge()
16
Refactoring 3a. Cleanup Move method
Rental each (Rental) rentals.nextElement()  
thisAmount each.getCharge()    
And we get rid of amountFor method.
17
Refactoring 4 Replace temp with query
while (rentals.hasMoreElements()) double
thisAmount 0 Rental each (Rental)
rentals.nextElement()   thisAmount
each.getCharge()   // Add frequent renter
points frequentRenterPoints  
// Add bonus for a two-day, new-release rental
if ((each.getMovie().getPriceCode()
Movie.NEW_RELEASE) each.getDaysRented()
gt 1) frequentRenterPoints   //
Show figures for this rental result "\t"
each.getMovie().getTitle() "\t"
Sting.valueOf(each.getCharge()) "\n"
totalAmount each.getCharge()
thisAmount each.getCharge()   // Add
frequent renter points
frequentRenterPoints   // Add bonus for
a two-day, new-release rental if
((each.getMovie().getPriceCode()
Movie.NEW_RELEASE) each.getDaysRented()
gt 1) frequentRenterPoints   //
Show figures for this rental result "\t"
each.getMovie().getTitle() "\t"
Sting.valueOf(thisAmount) "\n"
totalAmount thisAmount
18
Refactoring 5 Extract Method
// Add frequent renter points
frequentRenterPoints // Add bonus for a
two-day, new-release rental if
((each.getMovie().getPriceCode()
Movie.NEW_RELEASE) each.getDaysRented()
gt 1) frequentRenterPoints  
frequenRenterPoints each.getFrequentRenterPoint
s()
//add to rental class int getFrequentRenterPoints
() if ((getMovie().getPriceCode()
Movie.NEW_RELEASE) getDaysRented() gt
1) return 2 else return 1
19
Now get rid of hard-coded types
  • Replace type code with State/Strategy
  • Self-Encapsulate Field
  • Move Method
  • Replace conditional with Polymorphism

20
When to refactor
  • Rule of Three First time just do it. Second
    time, wince at duplication, Third time, refactor.
  • When you add functionality.
  • When you need to fix a bug.
  • As you do code review. (Active Reviews)

21
Refactoring Problems
  • Need more experience and study, but
  • Databases
  • Changing Interfaces
  • When you need to toss and start over
  • Performance

22
Bad Smells in code
  • Duplicated Code (Extract Method)
  • Long Method (Extract Method)
  • Large Class (Extract Class)
  • Long Parameter List (Remove Parameter)
  • Divergent Change (Extract Class)
  • Shotgun Surgery (Move Method, Move Field)
  • Feature Envy (Move/Extract Method)

23
More Bad Smells
  • Data Clumps (Introduce Parameter Object)
  • Primitive Obsession
  • Switch Statements
  • Parallel Inheritance Hierarchies
  • Lazy Class
  • Speculative Generality

24
Even More Bad Smells
  • Temporary Field
  • Message Chains
  • Middle Man
  • Inappropriate Intimacy
  • Alternative Classes with different interfaces
  • Incomplete library class
  • Data class
  • Refused Bequest
  • Comments

25
Tool Support
  • Smalltalk Refactoring Browser
  • IntelliJ (Commercial)
  • Eclipse
  • Others on web site

26
Next Time
How do we test this stuff?? How do we fit this
into a development strategy? JUnit and Agile
Development
Write a Comment
User Comments (0)
About PowerShow.com