Upload
earl-bennett
View
214
Download
2
Embed Size (px)
Citation preview
Today’s Agenda
More refactoring patterns
Software Testing and Maintenance 1
Introduce Null Object (1)
class Site … Customer getCustomer () { return _customer; }
class Customer … public String getName () { … } public BillingPlan getPlan () { … } public PaymentHistory getHistory () { … }
Customer customer = site.getCustomer ();BillingPlan plan;if (customer == null) plan = BillingPlan.basic ();else plan = customer.getPlan ();…String customerName;if (customer == null) customerName = “occupant”;else customerName = customer.getName (); …
Software Testing and Maintenance 2
Introduce Null Object (2)
class NullCustomer extends Customer { public boolean isNull () { return true; } public String getName () { return “occupant”; } public BillingPlan getPlan () { return BillingPlan.basic (); }
class Customer … static Customer newNull () { return new NullCustomer (); }
class Site … Customer getCustomer () { return (_customer == null) ? Customer.newNull () : _customer;
}
Software Testing and Maintenance 3
Introduce Null Object (3)
Customer customer = site.getCustomer ();BillingPlan plan;plan = customer.getPlan ();…
String customerName;customerName = customer.getName (); …
Software Testing and Maintenance 4
Replace Data Value with Object (1)
class Order public Order (String customer) {
_customer = customer; } public String getCustomer () { return _customer; } public void setCustomer (String customer) { _customer = customer; } private String _customer;
Software Testing and Maintenance 5
What if we need to add address or credit rating into a customer?
Replace Data Value with Object (2)
class Customer { public Customer (String name) { _name = name; } public String getName () { return _name; } private final String _name;}class Order … public order (String customer) { _customer = new Customer (customer); } public String getCustomer () { return _customer.getName (); } private Customer _customer; public void setCustomer (String customer) { _customer = new Customer (customer); }
Software Testing and Maintenance 6
Change Value to Reference
class Order { public order (String customer) { _customer = Customer.create (customer); }}class Customer { private Customer (String name) { _name = name; } static void loadCustomer () { new Customer (“Bilston Gasworks”).store(); new Customer (“Jeff Bridge”).store(); … } private void store () { _instances.put(this.getName(), this); } public static Customer create (String name) { return (Customer) _instances.get(name); } private static Dictionary _instances = new Hashtable ();}
Software Testing and Maintenance 7
Replace Magic Number with Sym. Constantdouble potentialEnergy (double mass, double height) { return mass * 9.81 * height;}
Software Testing and Maintenance 8
double potentialEnergy (double mass, double height) { return mass * GRAVITATIONAL_CONSTANT * height;}Static final double GRAVITATIONAL_CONSTANT = 9.81;
Separate Query from Modifier
int getTotalOutstandingAndSetReadyForSummaries () { readyForSummaries = true; return outstanding; }
Software Testing and Maintenance 9
int getTotalOutstanding () { return outstanding; }
void setReadyForSummaries () { readyForSummaries = true;}
Parameterize Method
class Employee { void tenPercentRaise () { salary *= 1.1; } void fivePercentRaise () { salary *= 1.05; }}
Software Testing and Maintenance 10
class Employee { void raise (double factor) { salary *= (1 + factor); }}
Replace Parameter with Explicit Methods
void setValue (String name, int value) { if (name.equals(“height”)) { _height = value; return; } if (name.equals(“width”)) { _width = value; return; }}
Software Testing and Maintenance 11
void setHeight (int arg) { _height = arg;}Void setWidth (int arg) { _width = arg;}
Replace Parameter with Method (1)
public double getPrice () { int basePrice = _quantity * _itemPrice; int discountLevel; if (_quantity > 100) discountLevel = 2; else discountLevel = 1; double finalPrice = discountedPrice (basePrice, discountLevel); return finalPrice;}
private double discountedPrice (int basePrice, int discountLevel) { if (discountLevel == 2) return basePrice * 0.1; else return basePrice * 0.05;}
Software Testing and Maintenance 12
Replace Parameter with Method (2)
public double getPrice () { if (getDiscountLevel() == 2) return getBasePrice() * 0.1; else return getBasePrice() * 0.05;}
private double getBasePrice () { return _quantity * _itemPrice;}
private int getDiscountLevel () { if(_quantity > 100) return 2; else return 1;}
Software Testing and Maintenance 13
Replace Constructor with Factory Method (1)class Employee { private int _type; static final int ENGINEER = 0; static final int SALESMAN =
1; static final int MANAGER = 2;
Employee (int type) { _type = type; }}
Software Testing and Maintenance 14
class Employee { static Employee create (int type)
{ switch (type) { case ENGINEER: return new Engineer (); case SALESMAN: return new Salesman (); case MANAGER: return new Manager (); default: // throw an exception }}
Replace Constructor with Factory Method (2)
Software Testing and Maintenance 15
static Employee create (String name) { try { return (Employee) Class.forName (name).newInstance(); } catch (Exception ex) { throw new IllegalArgumentException(“Unable to instantiate ” +
name); }}
Employee.create(“Engineer”);Employee.create(“Manager”);…
Encapsulate Downcast
Object lastReading () { return readings.lastElement ();}
Reding lastReading = (Reading) site.lastReading ();
Software Testing and Maintenance 16
Reading lastReading () { return (Reading) readings.lastElement ();}
Reding lastReading = site.lastElement();
Replace Error Code with Exception (1)
class Account … int withdraw (int amount) { if (amount > _balance) return -1; else { _balance -= amount; return 0; } } private int _balance;
Software Testing and Maintenance 17
Replace Error Code with Exception (2)
class Account … void withdraw (int amount) { if (amount > _balance) throw new IllegalArgumentException (“Amount too large”); _balance -= amount; } private int _balance;
Software Testing and Maintenance 18
Replace Error Code with Exception (3)
class Account … void withdraw (int amount) throws BalanceException { if (amount > _balance) throw new BalanceException (); _balance -= amount; } private int _balance;
Software Testing and Maintenance 19
Pull Up Constructor Body
class Manager extends Employee … public Manager (String name, String id, int grade) { _name = name; _id = id; _grade = grade; }
Software Testing and Maintenance 20
class Employee … public Employee (String name, string id) { _name = name; _id = id; }
class Manager extends Employee … public Manager (String name, String id, int grade) { super (name, id); _grade = grade; }
Extract Subclass (1)
class JobItem … public JobItem (int unitPrice, int quantity, boolean isLabor, Employee employee) { _unitPrice = unitPrice; _quantity = quantity; … } public int getTotalPrice () { return getUnitPrice () * quantity; } public int getUnitPrice () { return (_isLabor) ? _employee.getRate() : _unitPrice; } ….
class Employee… public Employee (int rate) { _rate = rate; } public int getRate () { return _rate; } private _rate;
Software Testing and Maintenance 21
Extract Subclass (2)
class JobItem … public JobItem (int unitPrice, int quantity, boolean isLabor) { _unitPrice = unitPrice; _quantity = quantity; _isLabor = isLabor; } public int getUnitPrice () { return _unitPrice; } ….
class LaborItem extends JobItem … public LaborItem (int quantity, Employee employee) { super (0, quantity, true); _employee = employee; } public int getUnitPrice () { return _employee.getRate (); }
Software Testing and Maintenance 22
Extract Subclass (3)
Modify calls to the constructor of the job item where a labor item is constructed
Software Testing and Maintenance 23
JobItem j = new JobItem (0, 5, true, kent);
JobItem j = new LaborItem (5, kent);
Form Template Method (1)
public String statement () { Enumeration rentals = _rentals.elements (); String result = “Rental Record for ” + getName () + “\n”; while (rentals.hasMoreElements ()) { Rental each = (Rental) rentals.nextElement (); // show figures for this rental result += “\t” + each.getMovie.getTitle() + “\t” + String.valueOf(each.getCharge()) + “\n”; } // add footer lines result += “Amount owed is“ + String.valueOf(getTotalCharge()) + “\n”; result += “You earned “ + String.valueOf(getTotalFrequentRenterPoints()) + “ frequent renter points”; return result;}
Software Testing and Maintenance 24
Software Testing and Maintenance 25
Form Template Method (2)
public String htmlStatement () { Enumeration rentals = _rentals.elements (); String result = “<H1>Rental Record for <EM>” + getName () + “</EM></H1><P>\n”; while (rentals.hasMoreElements ()) { Rental each = (Rental) rentals.nextElement (); // show figures for this rental result += each.getMovie.getTitle() + “: ” + String.valueOf(each.getCharge()) + “<BR>\n”; } // add footer lines result += “<P>You owe <EM> “ + String.valueOf(getTotalCharge()) + “</EM><P>\n”; result += “On this rental you earned “ + String.valueOf(getTotalFrequentRenterPoints()) + “ </EM>frequent renter points <P>”; return result;}
Form Template Method (3)
Software Testing and Maintenance 26
Customer Statement
Text Statement
HTMLStatement
Software Testing and Maintenance 27
Form Template Method (4)
class Statement … public String value (Customer customer) { Enumeration rentals = customer.getRentals (); String result = headerString(customer); while (rentals.hasMoreElements ()) { Rental each = (Rental) rentals.nextElement (); // show figures for this rental result += eachRentalString(each); } // add footer lines result += footerString(customer); return result; } abstract String headerString (Customer customer); abstract String eachRentalString (Rental rental); abstract String footerString (Customer customer);
Software Testing and Maintenance 28
Form Template Method (5)
class TextStatement … String headerString (Customer customer) { return “Rental Record for “ + customer.getName () + “\n”; }
String eachRentalString (Rental rental) { return “\t” + rental.getMovie().getTitle() + “\t” + String.valueOf(rental.getCharge() + “\n”; }
String footerString (Customer customer) { return “Amount owed is “ + String.valueOf(customer.getTotalCharge()) + “\n” + “You earned “ + String.valueOf(customer.getTotalFrequentRenterPoints()) + “ frequent renter points”; }
// similar for class HtmlStatement
Replace Inheritance with Delegation (1)
class MyStack extends Vector { public void push (Object element) { insertElementAt (element, 0); } public Object pop () { Object result = firstElement (); removeElementAt (0); return result; }}
Software Testing and Maintenance 29
Replace Inheritance with Delegation (2)
class MyStack { private Vector _vector = new Vector ();
public void push (Object element) { _vector.insertElementAt (element, 0); } public Object pop () { Object result = _vector.firstElement (); _vector.removeElementAt (0); return result; } public int size () { return _vector.size (); } public boolean isEmpty () { return _vector.isEmpty (); }}
Software Testing and Maintenance 30