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)
This package contains three sub-packages and the entirely static main driver class, Plan
containing the application entry point, main()
.
This method
input
),
dom
),
dom
),
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,
Plan.java,
sample output)
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,
FileInput.java,
TestInput.java)
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.
dom::FeatureList
interface.
dom::FeatureList
interface.
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,
Report.java,
sample output)
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.
java.util.Vector
is used to implement most one-to-many relationships,
java.util.HashMap
is used for one-to-many relationships where fast name-lookup is required,
java.util.Collections
,
java.util.Comparator
,
and
java.lang.Comparable
are used together to sort vectors of features,
java.util.Iterator
is used for all iteration through lists, whether made available in a public interface
or used privately,
(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, Company.java, Customer.java, Employee.java, Software.java)
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, FeatureList.java, Feature.java, Release.java, Software.java, DefaultFeatureListImplementation.java)
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, Feature.java, Priority.java, CustomerRequest.java, Employee.java, Customer.java, 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, Software.java, Release.java, Feature.java, ReverseFeaturePlanningOrder.java, DefaultFeatureListImplementation.java, java.util.Comparator, java.util.Collections)