Release Planning Application
Object-Oriented Design

By: Dave Penny
Date: Feb.20, 2002
Version 1.0

We have been asked by Professor Penny to deliver a completed program and associated documentation that will help his software company better plan releases of their software products.

The current document explains the detailed design of the delivered software using a combination of UML diagrams and prose. This design is based upon version 1.0 of the analysis document signed off by Professor Penny, on Feb.15, 2002.

(See also Javadoc, sample output, collected UML, collected source code)


As per Professor Penny's implementation requirements, the application is a console-oriented application written in 100% pure Java. We are using JDK1.3.

The top-level package is called plan. It contains all the code for the application.

(See also Javadoc overview)

Package plan

This package contains three sub-packages and the entirely static main driver class, Plan containing the application entry point, main().
This method

  1. parses the command line,
  2. causes the feature data to be input (calling package input),
  3. plans a release at the given capacity (calling package dom),
  4. plans a second release at the given capacity times the JUST_MISSED_RATIO and then subtracting the features present in the first release (again calling package dom),
  5. generates a report through various calls to the report package.

If any parameter error conditions arise, an internal routine dieUsage() is called that prints an error to standard error and then exits the program using System.exit(-1).

This entire sequence of events is shown in the sequence diagram below.

(See also Javadoc plan,, sample output)

Package input

The input package is responsible for reading a data source and instantiating dom objects from it. An object of type dom::Company is returned that roots all of the created objects.

For the time being, there is only a testing implementation of the FileInput interface. Depending upon the (phony) filename parameter, one of two internal routines are called that return either a pre-arranged set of objects, or a larger, randomly-generated set of objects.

(See also Javadoc input,,

Package report

This package provides utility routines for outputting reports. Currently only text-oriented reports to standard output are supported.

There is an entirely static class, Report that does all the work. This class encourages a "mix-and-match" approach to printing reports, providing the capability to print various sections of a report in some caller-defined sequence.

The various sections supported are as follows.

The internal (private) method customerDesirability() is responsible for formatting a string that captures how badly customers wish to see a feature in-plan. This string is used as one of the fields in the feature-detail report.

(See also Javadoc report,, sample output)

Package dom

This package implements the domain object model which consists of classes representing domain concepts as drawn from the object-oriented analysis. We present it in several pieces given below.

Note the use of a non-standard UML convention. We preface the names of certain attributes with either (p) or (rp) to indicate either a property or a read-only property. Properties have standard getter and setter methods that are excluded from the UML operations list for the class. Read-only properties only have getter methods. Values of read-only properties are set in the class constructor. In proper UML, these should be represented by a different compartment in the class symbols, however tool limitations preclude using this notation.

Wherever possible, we have re-used functionality from the standard Java class libraries to implement associations and related operations.

(See also Javadoc dom, java.util, java.lang)


A Company object roots all the objects that can be read from a data source. Objects of type Customer, Employee, and Software should only be constructed using the Company methods provided. These methods maintain a HashMap that allow for quick lookup of these objects by name. We anticipate that this approach will prove useful for code in the input package. Note that there is no facility provided for changing the names after construction.

(See also Javadoc dom,,,,


In the OOA, both Release and Software associate with Feature in a one-to-many fashion.

In order to support a convenient Report interface, we found it useful to define a FeatureList interface that both these classes implement. See the report section of this document for more details.

To save us some effort, we implement this FeatureList interface for both Software and Release classes in the same manner: by inheriting from DefaultFeatureListImplementation. Note that this is a case of implementation inheritance as the relationship between Release or Software and a feature list class would be better modeled by has-a than by an is-a relationship. In this case, expediency won out. The damage is contained by ensuring that no class outside of the participants should acknowledge the inheritance (in C++ we would use private inheritance to enforce this, however this language facility is not available in Java).

DefaultFeatureListImplementation does not implement all operations defined in the FeatureList interface (it leaves off getLabel()) and hence it is an abstract class. This method is used by the reporting package to label parts of the report that deal with a particular FeatureList. We felt the implementation of this method was best left to the deriving classes.

DefaultFeatureListImplementation provides additional methods beyond those required to implement FeatureList as a convenience to the deriving classes.

(See also Javadoc dom,,,,,


We implement the OOA customer requests feature association using one-way navigability from Feature as this is all the functionality that is required for the current application. The interfaces have been defined in such a way that changing this in the future should be straightforward.

Feature provides a method customerDesirability() that returns an overall measure of customer desirability for a feature. It returns the sum of the desirabilities across all customer requests, or 0 if there are none. Alternate approaches are possible for this, and in case of a requirements change it is the code in this method that will need to be modified. If in the future it is determined that mutliple approaches must co-exist at run-time, then this simple design must be changed in favour of an appropriate Behavioral design pattern.

The Priority class implements a type used to store the assigned priority of a feature, which is one of low, medium, or high. The constructor is private, and so only the three objects that this class itself instantiates will ever be created. We implement the java.lang.Comparable interface such that priority high is the greatest. We also implement routines to convert to and from a string representation, which ought to prove useful to code in the input package.

(See also Javadoc dom,,,,,, java.lang.Comparable)


Software has a method planRelease(capacity: double) that is used to plan releases. It creates and returns a new Release object. The algorithm is shown in the UML diagram.

The first part of the algorithm involves sorting the Feature objects in order from the most highly desirable to the least. To promote reuse, we use the standard standard sorting functionality in java.util.Collections. However, Feature does not define a native order (it does not implement java.lang.Comparable). This decision was made because of the judgment that the order of in-plan desirability is not a natural ordering for features (a better native ordering might be numerically by id or alphabetically by short description). As well, we did not want to tightly bind the sorting algorithm to the Feature class as this is something likely to change.

Instead we use an alternative Collections.sort(Vector,Comparator) method that takes as a parameter an object that implements the interface java.util.Comparator. We then implement this interface with the singleton class ReverseFeaturePlanningOrder. It is reverse because we wish more desirable features to be smaller than less desirable features so that the sort method (which only sorts ascending) will sort the most desirable features to the front of the vector.

(See also Javadoc dom,,,,,, java.util.Comparator, java.util.Collections)