The code in the project VideoRental is working, but
could use some design improvements. You are to make the following
refactorings to the code. As with all refactorings, these changes
should not change the behavior of the code, only the design.
Each code change will be submitted to your part of the repository with a subversion comment explaining what you have done.
Since we are trying to only change the design and not the behavior, we need some way to test the program. The Makefile has an option that will perform unit testing. Enter the command "make test". You will use the command to check that you haven't made any changes to the behavior.
Each individual refactoring must be committed separately, with a proper message in the subversion comment.
Do not, under any circumstances, add any new behavior.
statement is too long. Perform an Extract Method
Refactoring to replace the code in the switch statement
with a call to a new method amountFor that will do the work of the switch.
each of the method statement is not very clear.
Perform a Rename Parameter Refactoring to
rename this parameter to aRental.
amountFor is not really part of the
responsibilities of the class Customer. It is misplaced.
Perform a Move Method Refactoring to move this method to
the class Rental.
amountFor is not very descriptive. Perform a Rename Method
Refactoring to change this method name to getCharge.
thisAmount
in method statement is set and never changed, and is used twice.
Eliminate this variable with a direct method call by a Replace Temp with Query Refactoring.
Rental rather then
class Customer. Using a Extract Method
Refactoring, create a new method getFrequentRenterPoints
in class Rental and call it in
method statement to get the frequent renter points.
statement is performing multiple duties; including
accumulating the total charge for all movies. Perform a Replate
Temp with Query Refactoring to eliminate the
variable totalAmount by creating a private
method getTotalCharge in class Customer.
Use a call to this new method where totalAmount is being
output.
frequentRenterPoints by creating a
private method getTotalFrequentRenterPoints in
class Customer. Use a call to this new method
where totalAmount is being output.
getCharge in class Rental
accesses more information in class Movie than it does in
class Rental. This is a classic symptom of a method that
is in the wrong place. Perform a Move Method Refactoring to
move the functionality of the
method getCharge into a new method of the same name in
the class Movie. Leave the method getCharge
in class Rental and have it call the new method in
class Movie. It will be necessary to pass the number of
days rented.
getFrequentRenterPoints in
class Rental accesses more information in
class Movie than it does in class Rental.
Using an Extract Method Refactoring move the functionality of the
method getFrequentRenterPoints into a new method by the
same name in class Movie. Leave the
method getFrequentRenterPoints in the
class Rental and have it call the new method in the
class Movie.
getCharge and getFrequentRenterPoints
both contain things that may vary with type (Movie)
and should probably be kept together. Nothing to change yet, just an observation.
getCharge is in the class Movie.
It uses a switch according to the movie's category in the charge calculation.
If a new category is added the switch will need updated.
The method getCharge should behave according to the movie's category.
There is a problem that movies will change category, e.g., a movie will not be a
new release forever. Nothing to change yet. Just another observation.
Price in the
file Movie.hpp. This will serve as a base class for new classes,
and is the start of the Replace Type Code with State/Strategy Refactoring.
int. We will need to move from an
int to type Price. Nothing to change yet.
RegularPrice,
ChildrensPrice, and
NewReleasePrice.
Have all of them inherit from the class Price
getPriceCode in class Price.
Define a virtual method getPriceCode in each of the subclasses that returns the corresponding
category (ex. Movie::CHILDREN for the class ChildrensPrice).
price_code
in Movie.
price_code to Price*
setPriceCode to set the variable price_code to
a new instance of the correct Price object using a switch.
getPriceCode to call the method getPriceCode
on the Price object and return that value.
getCharge to move it from the class Movie to the
class Price. Don't forget to make it virtual. The
method getCharge in the class Movie should
delegate (i.e., call and let the other method do the work) to the
method getCharge in the class Price.
getCharge in the class RegularPrice.
Use the logic from the switch, comment out the case in the switch, then remove from the switch.
getCharge in the class ChildrensPrice.
Use the logic from the switch, comment out the case in the switch, then remove from the switch.
getCharge in the class NewReleasePrice.
Use the logic from the switch, comment out the case in the switch, then remove from the switch.
getCharge in the class Price is not longer directly used,
so make the method a pure virtual function. This will make the class Price abstract.
getFrequentRenterPoints together with
the method getCharge and move it to the class Price also.
getFrequentRenterPoints to the
class Price.
getFrequentRenterPoints in the class NewReleasePrice.