Here are the refactoring steps done in each subdirectory -- P1 ---------------------------------------------------------------- This is the original code that needs refactoring This base case is for establishing test results for verifying changes. -- P2 ---------------------------------------------------------------- The first thing we do is go to the large method in Customer and extract a method on the switch statement in the middle. We make a method for it in the same class Customer. The local data the switch code uses from the statement method must be passed in as an arg. compile, run tests, ... oops, the tests don't work. -- P3 ---------------------------------------------------------------- The previous refactoring doesn't work because the return value of the new method wa declared "int" and it should have been "double" Make this change... compile, test... all is well. -- P4 ---------------------------------------------------------------- Change several variable names in the new method to better reflect their pupose. compile, test, all is well -- P5 ---------------------------------------------------------------- move amount calculation out of class customer and into class rental the new method uses information from rental, and not from customer do this in 2 steps... the first is here... make the new method in the proper class. go to the existing method... remove its body and replace it with a delegation to the new method in the other class. compile, test, all is well. This first step used the existing JUnit tests to verify the new method works correctly. -- P6 ---------------------------------------------------------------- now go back into the original class ... remove the old method... the one with the delegation find all calls to the old method in all code (including all your JUnit tests) and change them to invocations of the new method in Rental compile, test, all is well. this step uses the working new method to verify the changes to the JUnit tests. -- P7 ---------------------------------------------------------------- now in Customer "thisAmount" is redundant replace temp with query to rental method directly -- P8 ---------------------------------------------------------------- now extract frequentRenterPoints as a new method elsewhere we will put this method in Rental since rental points are a function of renting, not of being a movie tape. use Extract Method and put this method first in Customer -- P9 ---------------------------------------------------------------- now continue extract frequentRenterPoints as a new method elsewhere we now move this new method into Rental since rental points are a function of renting, not of being a movie tape. use Move Method -- P10 --------------------------------------------------------------- now complete extract frequentRenterPoints as a new method elsewhere we finally get rid of the method in Customer and directly call the new one in Rental -- P11 --------------------------------------------------------------- more removing temps... replace totalAmount frequentRenterPoints accumulation in Statement in Customer... begin by replacing totalAmount with a query method in Customer call it getTotalCharge -- P12 --------------------------------------------------------------- more removing temps... replace totalAmount frequentRenterPoints accumulation in Statement in Customer... Now do the same for frequentRenterPoints call it getTotalFrequentRenterPoints -- P13 --------------------------------------------------------------- now one of the goals... the ability to make an HTML statement add the method htmlStatement to Customer slight mods to Statement, but it will call all the common methods we made -- P14 --------------------------------------------------------------- now let's attack that switch statement in getCharge, in class Rental we notice that the switch uses info from movie... the priceCode so the switch (if we have to have it) would be better in Movie where its control data is use Move Method on getCharge -- P15 --------------------------------------------------------------- now let's attack that switch statement in getCharge, in class Rental use Move Method to send frequentRenterPoints to movie too same reasoning... it uses Movie data -- P16 --------------------------------------------------------------- now... we can start replacing the switch in Movie with PolyMorphism simple subclassing Movie to allow each kind of Movie to have its own getCharge will not work... as a Movie can change its class during its lifetime... We will use State pattern to solve this... requires 3 refactorings Replace Type Code with State/Strategy Move Method Replace Conditional with Polymorphism First, Replace type code with State step one is Self Encapsulate Field to make sure all uses of the type code go through accessors methods. We are working in Movie class... -- P17 --------------------------------------------------------------- We are working in Movie class... now add the new classes needed for the State pattern we create abstract class Price and 3 subclasses to be the price code object ** compile ** but nothing to test then change the Movie class accessors to use the new class Price ** compile and test ** -- P18 --------------------------------------------------------------- We are working in Movie class... we now Move Method from Movie to Price... moving the method getCharge -- P19 --------------------------------------------------------------- We are still working in Movie class... we can now start Replace conditional with Polymorphism this will attack the switch in Price work on one leg of the switch at a time.. create an overriding method for it the idea it to override the parent class method that has the switch statement in it. start with subclass RegularPrice -- P20 --------------------------------------------------------------- We are still working in Price class... finish the other two override methods to complete the legs of the switch. compile and test before removing the switch -- P21 --------------------------------------------------------------- now make getCharge abstract in class Price... -- P22 --------------------------------------------------------------- ok... now do all this again for the method getFrequentRenterPoints in class Movie... why? because it uses price code information too... move it to Price -- P23 --------------------------------------------------------------- now finish making the move to price by creating the override method in the appropriate subclasses... and leave a concrete "default" in the parent class Price. -- P24 --------------------------------------------------------------- now what can we do... the two statement methods are very similar... there is common structure there but the contents of the string differes in each one. This is a candidate for a Template Method Strategy First the template method... we create a parent class for the statement to contain the skeleton of the algorithm. We subclass this for the text statement html statement in the subclasses we flesh out the abstract methods of the parent differently. First... we create the statement strategy... need objects for this also need to add an accessor getRentals to Customer. -- P25 --------------------------------------------------------------- ok complete the strategy with the version of the class for HTML... -- P26 --------------------------------------------------------------- next step... start extracting the differences between the two methods so you can form the skeleton of the template method. we note that each statement is composed of a header a footer/trailer lines for each movie rental let's start by extracting the header string part. -- P27 --------------------------------------------------------------- finish by extracting the middle per-rental string part. -- P28 --------------------------------------------------------------- ok... now we have a common method (value) in each of the strategy subclasses... elevate it to the parent level to make the template. -- P29 --------------------------------------------------------------- now we complete the strategy by making as single statement entry object for Customer.