Skip to content

HW2: Objects and Classes

Learning Objectives

This homework assignment is designed to help you learn several things. First, it will help you learn about the difference between static and non-static members. Second, it will help you learn about unit testing.

Background

Things-on-the-Wing Logo

The former JMU students that opened Wings-on-the-Wing have decided to sell other products (e.g., mozzarella sticks, jalapeno poppers) and have changed their name to Things-on-the-Wing. This change in focus has made them realize that their original design for the pricing system was bad. In particular, they realize that if they were to continue with the current design they would need to have a utility class for each product (e.g., a WingPricer, a StickPricer, a PopperPricer, etc.), and that each of these classes would be very similar (and, hence, contain duplicate code). So, they have changed the design so that they can have an object for each product rather than a utility class for each product.

For example, with the old design, if Things-on-the-Wing sold both wings and poppers they would need two almost identical utility classes and would use them as follows:

  double total;
  total = WingPricer.priceFor(6) + PopperPricer.priceFor(50);

With the new design they will need only one class and will use it as follows:

  double total;
  Pricer poppers, wings;
  wings = new Pricer(5, 7.49, 1.80);
  poppers = new Pricer(36, 17.99, 0.75);
  total = wings.priceFor(6) + poppers.priceFor(50);

Algorithms, Heuristics, Formulas, and Examples

None of the algorithms or formulas for this product are different from the earlier product. The only thing that must change is the code itself (i.e., the logic of the code will stay the same, only the structure and details of the code will be different).

The Classes to be Written

You must write a “normal” class named Pricer and a utility class named Test. The Pricer class is specific to stores like Things-on-the-Wing. The Test class can be used to test classes that are written for many different kinds of software products.

The Pricer Class

A Pricer object can be used to price any item that can be sold individually or in boxes.

The UML Class Diagram

The following UML class diagram provides an overview of the attributes and methods in this class (which must be in the hw2 package).

UML Diagram of the Pricer Class

Notice that there are several important differences between this “normal” class and the utility class from the previous assignment.

  • All of the attributes are now non-static and, so, belong to individual objects in the class rather than the class itself.
  • The attributes are now initialized in an explicit value constructor.
  • The methods are now non-static and, so, make use of the non-static attributes (that have different values for each object in the class).

Detailed Design Specifications

  1. The constructor must initialize the attributes of the object.
  2. The other methods must conform to the specifications for the WingPricer class, but must work for anything that can be sold in boxes or individually (not just wings).

The Test Class

The Test class is a utility class that can be used to simplify the process of testing other classes. Such a system is sometimes referred to as a test harness or a testing framework. Note: This class must conform to the course style guide (because it is not a test, it is a test harness.)

The UML Class Diagram

The following UML class diagram provides an overview of this class (which must be in the hw2 package).

UML Diagram of the Test Class

Detailed Design Specifications

In addition to the specifications contained in the UML class diagram, this class must conform to the following specifications.

  1. forEqualDoubles() must check to determine if the attributes expected and actual differ by more than the tolerance.
    1. If so, it must return false and print the values of description, expected, and actual (in that order) using the format string "%s Expected: %f, Actual: %f\n".
    2. If not, it must return true (and not print anything).
  2. forEqualInts() must check to determine if the attributes expected and actual differ.
    1. If so, it must return false and print the values of description, expected, and actual (in that order) using the format string "%s Expected: %d, Actual: %d\n".
    2. If not, it must return true (and not print anything).
  3. forEqualStrings() must check to determine if the attributes expected and actual differ.
    1. If so, it must return false and print the values of description, expected, and actual (in that order) using the format string "%s Expected: %s, Actual: %s\n".
    2. If not, it must return true (and not print anything).
  4. forFalse() must check to determine if the attribute named actual is false
    1. If so, it must return true (and not print anything).
    2. If not, it must return false and print the values of description using the format string "%s Expected: false, Actual: true\n".
  5. forTrue() must check to determine if the attribute named actual if true
    1. If so, it must return true (and not print anything).
    2. If not, it must return false and print the values of description using the format string "%s Expected: true, Actual: false\n".

An Existing Class

A main class (i.e., a class with a main() method) that you can use to test the Pricer class has already been written. It is named PricerTest and the source code (i.e., the .java file) is available at:

PricerTest.java

Unlike the WingPricerTest class from the previous assignment, this class makes use of the Test class that you have to write. So, you will not be able to test your Pricer class until you write the Test class.

Like the WingPricerTest class, this class does not conform to the style guide. As mentioned before, most organizations (including most faculty in the Computer Science Department at JMU) do not require that tests conform to the style guide.

Submission

You must submit (using Gradescope):

  1. Your implementation of the Pricer class.
  2. Your implementation of the Test class.

Do not submit the PricerTest class.

There is no limit on the number of submissions and no penalty for excessive submissions. Note that your submission will not be graded if it does not comply with the specifications. So, your submission should include a stubbed-out version of all of the classes. (This will allow you to get credit for the classes/methods that you do implement correctly.)

Grading

Your code will first be graded by Gradescope and then by the Professor. The grade you receive from Gradescope is the maximum grade that you can receive on the assignment

Gradescope Grading

Your code must compile (in Gradescope, this will be indicated in the section on “Does your code compile?”) and all class names and method signatures must comply with the specifications (in Gradescope, this will be indicated in the section on “Do your class names, method signatures, etc. comply with the specifications?”) for you to receive any points on this assignment. Gradescope will then grade your submission as follows:

Criterion Points Details
Conformance to the Style Guide 20 points (Partial Credit Possible)
Correctness 80 points (Partial Credit Possible)

Gradescope will provide you with hints, but may not completely identify the defects in your submission.

Manual Grading

After the due date, the Professor may manually review your code. At this time, points may be deducted for inelegant code, inappropriate variable names, bad comments, etc.

Since nobody will be looking over your shoulder, you can use any process that you would like to use. However, it is strongly recommended that you use the process described here.

Get Started

  1. Read and understand the entire assignment.
  2. Create a directory/folder for this assignment named hw2 under your existing CS159/hws/ directory/folder.

Stub-Out the Test Class

  1. Create a version of the Test class that contains all of the methods (with appropriate signatures), each of which should return false.
  2. Add the “javadoc” comments to the Test class and the methods in it.
  3. Check the style of the Test class and make any necessary corrections.

Understand the Test Cases

  1. Download PricerTest.java to the hw2 directory.
  2. Make sure there are no syntax errors in PricerTest.java. If there are, you probably need to fix the stubbed-out version of Test.java (since there are no syntax errors in PricerTest.java).
  3. Read and understand the test cases in PricerTest.java.
  4. By hand (i.e., using pencil and paper), calculate the expected answer for each of the test cases in PricerTest.java.

Copy and Rename WingPricer.java

  1. Copy WingPricer.java from the project directory/folder named hw1 to the directory/folder named hw2.
  2. Rename WingPricer.java to Pricer.java. (Hint: In VSCode, right-click on the file name and pull down to [Rename].)

Make Pricer.java a “Normal” Class

  1. Delete the initialization of all of the attributes (and save the file).
  2. Understand why this generated several syntax errors.
  3. Remove the final modifier from all of the attributes (and save the file).
  4. Understand why this resolved the syntax errors.
  5. Make all of the attributes non-static (i.e., remove the static modifiers).
  6. Understand why this generated several style errors.
  7. Understand why this also generated several syntax errors in the methods that follow.
  8. Rename the attributes (and save the file). (Hint: Highlight the attribute identifier, right-click on the highlighted identifier, pull down to [Rename Symbol], type the new identifier, and press [Enter]. Notice that this changes the identifier everywhere in the class.)
  9. Understand why this resolved the style errors.
  10. Remove the static modifier from all of the methods (and save the file).
  11. Understand why this resolved the syntax errors.
  12. Rename the formal parameters (a.k.a., formal arguments) and local variables.
  13. Write the explicit value constructor.

Implement the Test Class

  1. Add the forEqualInts() class.
  2. Add the forEqualStrings() class. (Hint: Be careful about how you compare String objects.)
  3. Add the forEqualDoubles() method. (Hint: You should probably use the static abs() method in the Math class.)
  4. Add the other methods.

Test and Debug the Pricer Class

  1. Run PricerTest.
  2. If there is any output it means that your code failed a test. Starting with the first failure, debug the relevant method in the Pricer class.
  3. Re-run PricerTest and repeat as necessary.

Help

In addition to those that were relevant for “Wings-on-the-Wing, an understanding of the following programming patterns will help you complete this assignment:

Questions to Think About

You don’t have to submit your answers to these questions, but you should try to answer them because they will help you determine whether or not you understand some of the important concepts covered in this assignment.

  1. Notice that the PricerTest class uses an array for the input values and uses a loop to run all of the test. Why is this better than the approach used in the previous assignment?
  2. How could you change the PricerTest class so that it keeps a count of the number of failed tests (and reports that number)?
  3. What compile-time errors are generated in the Pricer class if you make the attributes in it static? Why?
  4. Why does the PricerTest class test the wingPricer again after testing the popperPricer? In other words, what defects might this re-test identify? (Hint: Think about your answer to the previous question.)
  5. Why would it be nice to be able to overload methods in the Test class?