Inheritance
This page lists the milestone requirements for Milestone 3 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The third milestone involves refactoring our code to take advantage of inheritance and the use of interfaces. We’ll also need to update our documentation and unit tests accordingly.
General Requirements
This project is the first that requires ALL general requirements introduced in the “Hello Real World” project. Read this section carefully to see what is required for this particular milestone.
Assignment Requirements
This milestone should include the following features:
Interface
- A new
gamegrub.data.Item
interface that is implemented by all entree, side, and drink classes- It is highly recommended to do this by implementing the interface on the new base classes listed below.
- See below for the description of what this interface should contain
Base Classes
- New abstract base classes for each type of menu item:
- Entrees should inherit from
gamegrub.data.entrees.Entree
base class - Sides should inherit from the
gamegrub.data.sides.Side
base class - Drinks should inherit from the
gamegrub.data.drinks.Drink
base class
- Entrees should inherit from
- Each new base class should contain all elements that are shared by each type of menu item
- See below for the description of what the base classes should contain
Menu Class
- A new static class
gamegrub.data.menu.Menu
that contains the full menu- See below for the description of what this
Menu
class should contain
- See below for the description of what this
Unit Tests
- Updated unit tests for each menu item to check for proper typing
- Each menu item should implement the
Item
interface - Each menu item should inherit from the correct base class
- Each class except
Menu
andItem
should report near 100% code coverage.
- Each menu item should implement the
- Add a unit test class for
Menu
to confirm that each possible menu item is present in the menu.
Updated Documentation and Style
- Update the UML Class Diagram to represent the new structure of the code. This mainly involves adding relationship arrows and moving shared attributes and methods into base classes.
- Make sure all code is free from style errors using Checkstyle/Flake8.
Time Requirements
Completing this project is estimated to require 3-8 hours.
A rough estimate for this milestone would be around 1000 lines of new or updated code, and around 500 lines of redundant code removed. It could vary widely based on how you choose to implement the inheritance between the base classes and the interface. My model solution for this milestone now contains about 100 more unit tests in total. -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
Item
Interface - 25%- Base Classes - 30%
Entree
Base Class - 10%Side
Base Class - 10%Drink
Base Class - 10%
Menu
Class - 20%- Updated Unit Tests - 10%
Menu
Unit Tests - 10%- UML Class Diagram - 5%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
- Any portion of the project which does not meet the general requirements listed above will have a commensurate amount of points deducted.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
New Classes
Item Interface
The gamegrub.data.Item
class should be created as an interface that can be implemented by all other menu items. It should contain the following elements as abstract methods/properties:
- A getter for Price
- A getter for Calories
- A getter for Instructions
Each menu item (entrees, sides, and drinks) should be refactored to implement this interface. This will require some changes:
- Price and Calories is straightforward
- Instructions requires some changes
- Entrees - the Instructions list should now include each of the Toppings added to each item. This could be done via the new
Entree
base class. This also means that newly instantiated items should no longer have an empty Instructions list. However, it may be simpler to populate the list when it is requested instead of storing it. - Sides - the Instructions getter will need to be added, and it should just return an empty list since sides do not have instructions. This can be done via the new
Side
base class. - Drinks - no changes needed
- Entrees - the Instructions list should now include each of the Toppings added to each item. This could be done via the new
Accordingly, the unit tests for some of these classes will need updated, as discussed below.
Base Classes
Each of the three types of menu items should directly inherit from a new abstract base class. These classes should not be instantiated!
gamegrub.data.entrees.Entree
is the base class for all entree items. It should include the following elements that are common to all entree classes:- Base - attribute with getter and setter.
- Toppings - attribute with getter, Add Toppings and Remove Toppings methods.
- Price - abstract getter. This should be overridden in the subclass to return the correct price.
- Calories - abstract getter. This should be overridden in the subclass to return the correct calories.
- Instructions - getter. This should be overridden in the subclass to return the correct list of instructions.
- One easy way to do this: the method in the superclass could be used to add the list of toppings to the list, and then the subclass method could call the superclass method as part of its code and then add the ingredient changes itself.
gamegrub.data.sides.Side
is the base class for all side items. It should include the following elements that are common to all side classes:- Size - getter and setter.
- Price - abstract getter. This should be overridden in the subclass to return the correct price based on the size.
- Calories - abstract getter. This should be overridden in the subclass to return the correct calories based on the size.
- Instructions - getter. This should simply return an empty list, and does not need overridden.
gamegrub.data.drinks.Drink
is the base class for all drink items. It should include the following elements that are common to all drink classes:- Size - getter and setter.
- Price - abstract getter. This should be overridden in the subclass to return the correct price based on the size.
- Calories - abstract getter. This should be overridden in the subclass to return the correct calories based on the size.
- Instructions - abstract getter. This should be overridden in the subclass to return the correct list of ingredients changed.
You may choose to implement the Item
interface on the three base classes described below, which will then be inherited by each menu item, instead of explicitly implementing the interface on each menu item itself. Some of the elements described on these base classes are already defined in the Item
interface, so if you implement the interface at the base class level you do not need to redefine the abstract methods from the interface within the abstract base classes. Either approach is valid, though going through the base class makes things simpler down the road!
If you choose to inherit from the Item
interface in the base classes in Python, the base class should not inherit from ABC
- that is already covered as part of the interface. If you do, Mypy will present an error stating that it “cannot determine consistent method resolution order.”
You may also need to refactor some private
attributes (with double underscores in Python) to protected
attributes (single underscores in Python) as they move from the subclass to the superclass. In Java, these are just attributes as expected. In Python, it is simplest to declare those in the constructor of the superclass (such as self._size = Size.JUNIOR
), then make sure you call that constructor using super().__init__()
in the subclass’ constructor.
Menu Class
The gamegrub.data.menu.Menu
class should be a class that has static, class-level getter methods for these four elements:
entrees
- a list ofItem
elements containing an instance of all available entrees (5 in total).sides
- a list ofItem
elements containing an instance of all available sides. Since each side is available in three sizes, the list should include an instance of all three sizes of each side item (9 in total).drinks
- a list ofItem
elements containing an instance of all available drinks. Since each drink is available in three sizes, the list should include an instance of all three sizes of each drink item (9 in total).fullmenu
- a combined list of all menu items (23 in total).
In Java, these lists should use a subclass of the List interface. In Python, these methods should use the built-in Python list data type. Since they are static methods, they cannot be constructed as Python properties using the @property
decorator.
Unit Tests
The following updates must be made to the existing unit tests in this project to accommodate these code changes:
Entrees
- When a new object is created:
- The instructions list should now contain entries for each of the toppings present by default
- Check inheritance:
- Check if the object inherits from the correct base class
- Check if the object implements the
Item
interface
- For each topping:
- Check that adding or removing the topping will add or remove that element from the instructions list.
Sides
- When a new object is created:
- The instructions list should be empty
- Check inheritance:
- Check if the object inherits from the correct base class
- Check if the object implements the
Item
interface
Drinks
- Check inheritance:
- Check if the object inherits from the correct base class
- Check if the object implements the
Item
interface
To check for type compatibility, use the object instanceof Class
operator in Java, or the isinstance(object, Class)
method in Python as part of an assertion statement. Hamcrest also includes a few matchers for this, such as isA
(Java) or instance_of()
(Python).
Menu
- Test that the entrees list contains an instance of each entree
- Test that the sides list contains an instance of each side for each size
- Test that the drinks list contains an instance of each drink for each size
- Test that the full menu list contains an instance of each menu item in the lists above