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.
The course svn repository is at http://classes.cs.kent.edu/courses/cs43901/svn/001/$USERNAME/cs43901_student and the shared folder is at http://classes.cs.kent.edu/courses/cs43901/svn/001/cs43901_lecture/
Copy the project folder (VideoStore) and make changes committing them in subversion. 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 or change existing behavior.
Do the following:
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 unclear.
Perform a Rename Parameter refactoring to
rename this parameter to aRental
.
amountFor
is not 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
.