Domain Modeling: Concepts and Activities

UML class diagrams as a conceptual models

A conceptual model captures the important concepts and relationships in some domain.

Concepts are represented by classes, while relationships are represented by associations.

Packages represent groups of related classes and associations.

Objects represent specific instances of classes.

For example a business might organize its concepts and relationships into three packages:

Classes

In the hr package we might find the Position and Person classes. Typical attributes of persons and positions can be listed in the attribute compartments of the respective class icons. Typical operations performed by persons and positions can be listed in their operation compartments:

In this example, an object representing a position, vice president for example, has a title attribute of type String and an execute operation that takes a task, t, as an input, and outputs a result.

An object representing a person has four attributes: last name, first name, and Social Security number, all of type String, and a salary of type Money and with initial value $0.0. The person class has no operations specified at this point.

It is often the case that operations correspond to responsibilities and are not assigned to classes until the design phase. For this reason operation compartments are often suppressed in domain models. Attribute compartments can also be suppressed if they are not needed.

Note that the "-" sign indicates that the scope of an attribute or association endpoint is private, visible only inside of the class. Other possible scopes are:

+ = public = system-wide scope
~ = package scope
# = protected = subclass scope

Generally speaking, the default for an attribute or association endpoint is private, while the default for an operation is public.

Associations

The relationship "Position X is filled by person Y" can be represented by an association connecting Position and Person:

Note that the name of an association can be decorated by a tiny arrow showing which way the association is read. This helps distinguish a relationship from its inverse.

Note that the endpoints of an association can be decorated by:

name = the name used by objects on one end to refer to objects on the other end. For example, an employee refers to his position as his "role" while a position refers to the employees filling it as its "actors."

multiplicity = the number of objects that can be related to a given object. For example, a given position, vice president, say, can be filled by by 0 or more persons (indicated by "*"), while a given person, Joe Smith, say, can fill one position.

Objects

Specific persons and positions can be represented using objects. Specific instances of the filledBy relationship can be represented by links connecting the participating objects:

Implementation

It's too early to speak of implementation, but the fact is that UML class diagrams can be translated into object-oriented languages like Java, C++, and C#. For those interested, here's a preliminary sketch:

HR.java

Stereotypes

Similar concepts may appear under different names in diverse domains. The more general concept that a class fills can be indicated by a stereotype.

For example, Peter Coad classifies business concepts into four stereotypes:

<<entity>>

<<type>>

<<role>>

<<event>>

Here's an example of using stereotypes from the marketing package:

Note that some association endpoints don't have names. The default name is the name of the class. For example, the Sale endpoints of the associations sold and soldTo associations would be named "sale" (lowercase "s").

Note that the association connecting Item to Product has no name. This is often done if the name would make the diagram harder to understand from the domain's point of view. In fact, this association represents the relationship:

Item X is an instance of Product Y

In other words, a grocery store might have 20 boxes of Cheerios on a shelf. Each box is an item, perhaps distinguished in the inventory database by a serial number. All of these boxes are instances of the product Cheerios.

Navigation

Another property of an association endpoint is navigability, which can either be true or false.

When an endpoint is navigable, it is decorated by a barbed arrowhead:

The arrowhead indicates that every client object uses, has, or knows a provider object, but that the provider object doesn't know about the client objects that use it.

In the example above Item is a client of Product, and Product is a provider for Item.

In the grocery store's inventory database every box of Cheerios knows that it is a box of Cheerios, but the Cheerios product is just a description of the product and perhaps the contact information for the supplier. It doesn't know the identities of the millions of boxes of Cheerios in the world.

In domain modeling the rule of thumb is that if you don't know if an endpoint should be navigable or not, then assume it is not. Often the distinction between client and provider is made during the design phase.

Generalization

Another special relationship is the relationship between a subclass and a superclass. This relationship is shown with the generalization arrow. In the following diagram we say that A generalizes B which generalizes C and D:

 

Java terminology is better. We say that C and D extend B which extends A.

The transitive closure of the generalization relationship is the subclass relationship. X is a subclass of Y, written X <: Y, if X is connected to Y by a chain of zero or more generalization arrows. It's easy to see the subclass relationship is transitive and reflexive:

X <: X
X <: Y <: Z => X <: Z

Semantically, X is a subclass of Y means that instances of X can be substituted for instances of Y in most contexts.

This means that any operation an instance of Y can perform can also be performed by an instance of X (although perhaps using a different algorithm.) This is another way of saying that a subclass inherits the attributes and operations of all of its superclasses.

Here's an example of an inheritance hierarchy:

Note that Shape has six subclasses:

Circle <: Ellipse <: Shape, hence Circle <: Shape
Pentagon <: Polygon <: Shape, hence Pentagon <: Shape
Hexagon <: Polygon <: Shape, hence Hexagon <: Shape

Also:

Shape <: Shape

Therefore, every Circle object, for example, inherits position and size attributes from the Shape superclass.

Furthermore, in this example the Circle object will be able to access these attributes because they have protected or subclass scope as indicated by the "#" symbol.

Here's another example:

Note that our substitution semantics applies in all of these situations:

A jet can substitute for a plane which can substitute for a vehicle.

A hexagon can substitute for a polygon which can substitute for a shape.

However:

A jet can not substitute for a Car.

A hexagon can not substitute for an ellipse.

There are several things wrong with the following inheritance hierarchy:

Here's how it might be refactored into a better design:

Note that multiple inheritance is allowed in UML, even though this feature isn't supported in some object-oriented languages (like Java):