Refactoring Programs (Again)
This project is intended to get you to practice some of the programming and
design techniques discussed in class recently and consists of four activities:
- understand the current code
- refactor the current code
- test the refactored code to verify that it still works
- add additional functionality to the refactored code
The code to simulate a game of roulette is given below although you will focus your efforts on Game
class (declared in game.h
and implemented in game.cpp).
Understanding
You should analyze the code above and determine the purpose of each of
the classes written (i.e., what role does it play in the program). There
are some comments currently in the code, but your analysis should go beyond
these comments. However, it should not be necessary to write more than
a paragraph for each class. In order to determine each class' role,
you should focus on how it interacts with other classes in the program
or how a particular task is accomplished.
To help direct your analysis, consider the following questions:
- Why is it not necessary for game.h to include
iostream?
- Why is Bet a struct and not a class?
- How many classes know about the Bet struct?
- What code would be need to be added to game to allow the user to make
another kind of bet that paid one to one odds and was based on whether the
number spun was high, between 19 and 36, or low, between 1 and 18?
- What code would need to be changed to add error checking to the characters
input by the user to choose a bet?
Refactoring
You should examine the code given and refactor it to remove as much of the conditional
logic in the play function as possible with an inheritance hierarchy of bets.
Your refactored code should attempt to minimize the amount of new code required
to add another type of bet. You may create (and comment) any new
classes you want to solve this problem.
To help direct your refactoring, consider the following questions:
- What functions would make sense as behaviors of a Bet hierarchy
(i.e., make bets open to extension)?
- What functions would help improve the code in the play function
(i.e., close it to modification)?
- What functions can be completely implemented in the Bet
super-class (i.e., are constant across the hierarchy), and which completely
in the Bet sub-classes (i.e., must be specialized across the
hierarchy)?
- Should Bet remain a struct or be re-implemented as a class?
- How should the Game
class create the correct Bet sub-class?
Testing
You should provide a set of tests that verify your modified program
still works as intended. Tests can be in the form of input data files, driver
programs, or other classes that verify every line of code written works as
intended.
To help direct your testing, consider the following questions:
- How can you test a program that is primarily based on randomness?
- How can you easily remove the randomness?
- Can you make it easy to turn randomness on and off?
- Can you make it easy to test several different kinds of bets?
- How should you package your testing code so that it is easy to run
repeatedly?
Improving
Finally, using your improved code, you should add the three bets given
in the original specification not implemented code given to you, adding as
little new code as possible.
Compare the effort to create a new bet in your improved code to how you would
have done it in the original code.
- In what ways is the refactored code simpler?
- In what ways is the refactored code more complex?
- What trade-offs did you make when refactoring your old code?
- Which code do you prefer and why?
Comments?