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

Warning

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.

  • All code must be object-oriented.
    • All executable code must be within a class
      • Python package files such as __init__.py and __main__.py are exempt.
    • Classes must be organized into packages based on common usage.
  • All projects must include automation for testing, style checking, and documentation generation.
    • Java: Use Gradle with the application, jacoco, and checkstyle plugins.
    • Python: Use tox configured to use Python 3.10 and a requirements file to install libraries.
  • All code must properly compile and be executable.
    • Java: It must compile and execute using Gradle.
    • Python: It must execute using Python 3.10. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check.
  • All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
    • Java: Use Checkstyle 10.6.0+ and the Google Style Configuration.
      • You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
    • Python: Use Flake8 with the flake8-docstrings and pep8-naming plugins. Code should conform to PEP 8 style with Google style docstrings.
  • Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
    • Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
    • Python: Use pytest. You may choose to use Hamcrest for assertions.
  • Where specified, code should contain appropriate documentation comments following the language’s style guide.
    • In any class that should be documented, every method in that class should have complete documentation comments.
    • Java: Use javadoc to generate documentation.
    • Python: Use pdoc3 to generate documentation.
  • Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.

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
  • 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
  • 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
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 and Item should report near 100% code coverage.
  • 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.

Expected Scope

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.

Code Review

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

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.
Many Valid Approaches

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.

The gamegrub.data.menu.Menu class should be a class that has static, class-level getter methods for these four elements:

  • entrees - a list of Item elements containing an instance of all available entrees (5 in total).
  • sides - a list of Item 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 of Item 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
Checking Types in Unit Tests

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).

  • 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