JMU CS345 - Software Engineering
Help Policies Solutions Study-Aids Syllabus Tools
Homework: Design Patterns


1 Purpose

The primary purpose of this assignment is to help you review (and demonstrate that you have acquired) the knowledge and skills required to use design patterns.

2 Overview

As you know from earlier assignments, SagaciousMedia is a (fictitious) company that develops educational hardware, software, and content for both the formal and informal education markets. To date you have written several components for their application named Gradient.

They have decided that their earlier design was not flexible enough. Hence, for this assignment you must implement their new and improved design. In particular, you must use the Composite Pattern to make it possible to have arbitrarily complicated course structures. You must also use the Factory Method pattern to improve the creation of grades from their String representations.

3 Starting Point

This assignment builds on H1 and H4. You may start with either your solution to those assignments or mine. However, there is no guarantee that my code is correct (though I think it is); you are responsible for any and all mistakes in your submission. In other words, there are no intentional defects in my code, but you are responsible for any that might exist.

4 Documents

Sagacious Media has created several new documents for this release.

Note that these documents provide details where they are needed (e.g., where they have changed from the earlier designs) and omit them where they are not (e.g., where they haven't changed from the earlier designs).

5 Testing

As always, you must use JUnit, your JUnit test suite must cover all statements and all branches (as measured by EclEmma) in all of the classes/enums you submit, including the classes/enums from earlier assignments (whether you actually wrote them or I did), your tests must be in a package named testing, and each test class must include the word "Test" in its name.

6 A Recommended Process

As before, the tasks that were identified by the team at Sagacious Media are organized by story. Hence, though they are numbered so that they can be referred to in documents and conversations, the numbers should not, in any way, influence the order in which you complete them.

In this case, it is particularly important that you give some thought to the order in which you make changes to the existing code, since it can be done fairly efficiently or very inefficiently. In other words, the refactoring tool in Eclipse can be very helpful if used thoughtfully or it can create an enormous amount of unnecessary work if used sloppily.

I would suggest you sequence your activities as follows. However, you should think about how this process will work for you given the way you implemented your tests.

  1. Read and understand all of the documents.
  2. Create a new project for this version.
  3. Copy the SizeException and Missing classes from the previous version.
  4. Copy the Grade class from the previous version.
  5. Refactor the Grade class, renaming it to LeafGrade.
  6. Implement the Grade interface.
  7. Implement the AbstractGrade class.
  8. Modify the LeafGrade class so that it now specializes the AbstractGrade class.
  9. Modify the tests as necessary. Specifically, when you refactored the Grade class and renamed it LeafGrade, Eclipse made the change everywhere. In some cases (e.g., in List objects), you should change it back to Grade (e.g., from List<LeafGrade> to List<Grade>).
  10. Perform regression testing on the LeafGrade class (using the tests that you originally wrote for the Grade class and debug it if necessary.
  11. Copy the other classes and interfaces from the grading package of the previous version.
  12. Make whatever changes are necessary to these classes (e.g., if a class used to construct a Grade object it will now need to construct a LeafGrade object).
  13. Perform regression testing on all of these classes and debug them if necessary.
  14. Implement the CompositeGrade class.
  15. Test and debug the CompositeGrade class.
  16. Modify the CourseReader class so that it no longer uses the Category and Course classes.
  17. Test and debug the CourseReader class.
  18. Test and debug the complete system. When running the main class it is a good idea to include the full path and file name in the command-line/run arguments, otherwise, depending on where you put the files, you will get a FileNotFoundException. (Remember to put the whole thing in quotes if it contains spaces.)

7 Submission

You must submit (using Gradescope) a .zip file named sub5.zip that contains:
  1. "Your" implementation of the required interfaces/classes/enums in the appropriate package(s).
  2. JUnit tests for all of the classes/enums you submit (in a package named testing) and all of the data files used by your JUnit tests (in the same directory).

There is no limit on the number of submissions and no penalty for excessive submissions.

8 Grading

Your submission will be graded as follows:

As always, points will be deducted manually (i.e., outside of Gradescope) for code that is unclear, inelegant, and/or poorly documented.

9 Questions to Think About

You need not submit answers to the following questions, but you should probably answer them before you start writing any code.

9.1 Questions about the Design

The design of this version is significantly different from the design of the previous version.
  1. Grade is now an interface, not a class. Why?
  2. Some of the functionality that was in the Grade class has been moved into the AbstractGrade class and some of it has been moved into the LeafGrade class. Why?
  3. There is a new CompositeGrade class that contains a collection of Grade objects and uses a Filter and/or Strategy to calculate the numerical grade for the collection.
  4. What design pattern is being used? What are the benefits?

9.2 Questions about the Implementation

There are almost always different ways to implement specifications. As when solving any problem, you should consider the different alternatives, evaluate them, and choose the best one. Some things to think about in this regard include the following.
  1. You should almost never catch and re-throw the same exception though sometimes you may need to catch one and throw another. Why?
  2. You shouldn't use exception handling when an if statement can be used. For example, you should almost never catch a NullPointerException you should, instead, use an if statement to see if the object is null. Why?
  3. Declarations should be as flexible and generic as possible. Instantiations must be specific. Why?

Copyright 2025