Just as in the real world, characters (people and animals) have both state (i.e., data, e.g., where they are in the world and their mood), and are capable of actions (e.g., walking, eating, etc.). We want our computational objects to encapsulate both data and functions (called methods when they are associated with an object).
This first course project is split into two parts: a design document and an implementation refactoring. In doing this project, you will gain experience with methods to specify an object's behavior and with basic UML class diagrams.
For this project you will be provided the code for a virtual world program
and a UML diagram of the classes used to structure this program. The program,
as given, is written in a non-object-oriented style like that seen in
CPE 101. In particular, the vast majority of the functionality is defined
as static
methods in the Functions
class (with a
few methods defined in EventComparator
, Point
,
and VirtualWorld
). You should take some time to skim the
provided code to get a basic sense of how it is organized. (You might
question the quality of this design (which is great!), especially if you have
some experience with object-oriented design; you should, however, note that this
is a perfectly valid approach (though some parts are intentionally structured
for later improvements) that might actually serve you well in a language that
does not directly support object-oriented programming, such as C in CPE 357.)
You must identify the behavior associated with each class (i.e.,
the behavior exhibited by instances of the class) and move that behavior
from the standalone static methods in Functions.java
to
(static or non-static, as appropriate) methods defined within the class.
For this assignment, you will not add new functionality (aside from some
accessor/mutator methods, only as needed).
You are encouraged to develop the UML design document first, however, you are also welcome to simultaneously work on the code refactoring. If you do start refactoring the code, you are encouraged to implement the refactoring incrementally so that your refactored program executes properly at each step.
Functions.java
to the appropriate class
The provided UML diagram was created using the freely available yEd Graph Editor. You may use this on the department workstations or install it on your own machine. This editor was selected for its simplicity in the number of features available for UML editing (our intentionally limited use of UML is sufficiently supported without a potentially overwhelming number of additional features).
On the department workstations, you can execute yEd as follows:
java -jar /home/akeen/public/yed/yed.jar Methods.graphml
Selecting a class diagram, right-clicking, and then selecting the
Properties option will open a dialog window to allow editing the
class diagram. Selecting the UML tab will then allow editing the
lists of attributes and methods. (This dialog window can
be resized; I realized this too late. For those that like living
dangerously, the .graphml
file is a plain text format
that can be edited directly.)
static methods
in Functions.java
are moved to be appropriate instance methods for the various classes.
As you are working on this, you may want to refer to the actual code. And for the
next part of this assignment you will in fact refactor the code based on your UML design.
The provided source code is available on PolyLearn.
Details on building and executing the program are given in the description of Programming Assignment 1.
In general, this assignment will take some careful thought and design, so take the time to read the provided code and to plan your actions before making modifications (some tips for identifying methods are given later in this document). Read, think, design, and then code.
Note that good design is somewhat subjective. Even so, for the vast majority
of the methods, there is a single "correct" class into which the method should
be moved. For a small number of methods, one could reasonably argue in favor
of a few different classes. For example, there are multiple classes with which
one could reasonably associate the adjacent
method. Do your best
to make reasonable decisions based on the design discussion in lecture and
document these decisions in your design document.
With the exception of some constant (static final
) values,
all data attributes should be private
and, when possible,
final
. (Point
is the exception to this since
each value acts as a constant value akin to an integer.)
Methods should also be private
unless public
access is necessary (i.e., it is used outside of the defining class).
For this project, every method should be either private
or public
(it is often better to avoid the default of
package-protected).
Your "design document" will consist of two parts: an updated UML diagram
and a text document. First, copy the provided UML diagram to
Methods.graphml
. Then update this copy to reflect all
method/data movements as well as any newly created accessor/mutator methods.
Second, in a plain text file (named DESIGN.txt
) list each of
the methods that was left in the Functions
class and give a
brief justification for why this method was not moved. You should also
list each method that you feel could be reasonably placed in multiple
classes and note 1) the class you selected and 2) the reason for that
selection.
The provided source code uses objects to hold data; these objects have no methods (no behavior). Your task for this assignment is to identify the behavior associated with objects (instances) of a class and move this behavior from standalone functions to methods defined within the class.
Reasonable steps for this assignment include (additional, programming-specific, tips are given in Programming Assignment 1):
Run the program. You can use -fast
, -faster
,
-fastest
on the command-line to increase the rate at which
actions are executed. You can use the arrow keys to shift the view of
the virtual world.
Read (skim) the source code.
View the provided UML diagram to see the name of each class and the data stored within instances of each class.
Identify methods that interact with the data stored within an object (and identify the object's class).
Match behavior to classes.
When looking for good matches of functions with classes, consider the following hints:
If the attribute of an object is accessed directly via a dot (e.g., entity.name), then either the function in which this access appears should be defined in the object's class, or the access should be done via an accessor method.
If a method determines its behavior based on the "kind"
(e.g., the the various values of ActionKind
or
EntityKind
)
of object it is manipulating, then this method should likely
be moved into that object's corresponding class (do not
introduce separate classes at this time).
There are some methods that may remain as static methods, but that are reasonably moved into another class (these are often considered "utility" methods derived from decomposing a problem into simpler methods).
There are some methods that will reasonably remain as static
methods in the Functions
class because there are
not yet appropriate classes for them.
Run the program to verify that it behaves as expected.
Your submission of your design document will consist of the following files. Add both of these files to your Project 1 Submission file on PolyLearn!