Do a grammatical parse of the problem requirements (use cases) for nouns and noun phrases.
List all candidates you can think of, then prune to an essential set that covers all the requirements.
Identify collection classes (e.g. List, Queue) for managing collections of items.
Research class libraries for classes that you can use or inherit from. Don't reinvent the wheel; use proven code.
Keep in mind the distinction between classes and objects (instances of classes). E.g., a corvette would be an object of type vehicle or car, it is unlikely that corvette would be a class.
Don't worry about UI classes at this point.
Attributes are often nouns from the candidate classes list that
got pruned.
Attributes become the instance variables in a class.
Most attributes will come directly from the data dictionary.
Identify the operations suffered by and required of each class. For example, if you are considering a Stack class, ask: "What can I do to a stack? What can happen to a stack?"
Focus your thinking on one class without considering its environment. For example, addRecord is a never a method on the Record class.
Don't think about which procedures are going to use the stack or what is going to be pushed on the stack.
Don't think about data structures or algorithms. Those decisions are best left until detailed design unless there is a feasibility problem.
Look through the problem requirements for verbs. These often map directly to a method.
Read about class relationships.
This is the hardest part of design. There are many decisions to make:
Inheritance or Object Composition?
Consider:Inheritance or Interface?
Inheritance allows programmer to modify operations by overriding them.
Inheritance relationships can be easily extended in the future.
Inheritance exposes the internal structure to it's subclasses - with association, the objects remain encapsulated.
Inheritance carries an assumption of substitutability, promoting a versatile design.
Composition is simpler.
Composition allows for implementation independence.
Composition classes can't modify operations by overriding, thus the interface is more stable.
Learn more: [Summary] [Inheritance Critique]
Consider: Inheritance allows for sharing structure and behavior, Interfaces allow for sharing behavior.Aggregation or Dependency?
Consider: Does one class use another, or does it aggregate another?
Be sure to document the rationale for your decisions in the Design
Rationale.
Write a complete class header.
Write the signature for each method. The method signatures become the skeleton of your program.
Code your class interface (not implementation) and document it as javadoc comments.
Compile your class interface and remove any syntax errors.
If you are a disciple of Test Driven Development you write your unit tests now.
Inheritance is implemented using the extends keyword. In UML, inheritance is denoted by a line with a triangle placed toward the superclass. Interface inheritance uses the implements keyword and has a dotted line.
Aggregation is implemented using instance variables.
Every truck has a tire. (Truck is the whole, tire is the part).
class Truck extends VehicleIn UML, aggregation is denoted by a line with a diamond placed toward the aggregating class.
{ ...
private Tire[ ] tires;
}
Composition, a strong form of aggregation, indicates that the components can't exist without the aggregate. The component can't belong to more than one aggregate. E.g., a window is composed of a slider (the slider can't exist without a window). The relationship is of a structural nature. In UML, composition looks like aggregation with a filled diamond.
Dependency indicates coupling.
Typical Implementation
class DependentClass
{
...
void function1(ReferencedClass parameter1)
...
ReferencedClass function2(...) { ... }
...
void function3(...)
{
ReferencedClass
localvariable = new ReferencedClass();
int x = ReferencedClass.staticMethod();
}
}
In UML, association is denoted by a solid line connecting two classes.
Typical Implementation
class Man
{
Woman wife;
...
}
class Woman
{
Man husband;
...
}