Ivan Marsic • Rutgers
University 130
Suppose now that we wish to extend the diagram in Figure 3-12 to show the states Buy, Sell, and Hold, which we defined in Example 3.2 above. These states are a refinement of the Traded state
within which they are nested, as shown in Figure 3-14. This nesting is depicted with a surrounding boundary known as a region and the enclosing boundary is called a composite state.
Given the composite state Traded with its three substates, the semantics of nesting implies an exclusive OR XOR relationship. If the stock is in the Traded state the composite state, it must
also be in exactly one of the three substates: Buy, Hold, or Sell.
Nesting may be to any depth, and thus substates may be composite states to other lower-level substates. For simplicity in drawing state transition diagrams with depth, we may zoom in or
zoom out relative to a particular state. Zooming out conceals substates, as in Figure 3-12, and zooming in reveals substates, as in Figure 3-14. Zoomed out representation may improve
comprehensibility of a complex state machine diagram.
Concurrency
Figure 3-15
Applications
State machine diagrams are typically used to describe the behavior of individual objects. However, they can also be used to describe the behavior of any abstractions that the developer is
currently considering. We may also provide state machine diagrams for the entire system under consideration. During the analysis phase of the development lifecycle described in Section 2.3,
we are considering the event-ordered behavior of the system as a whole; hence, we may use state machine diagrams to represent the behavior of the system. During the design phase described in
Section 2.4, we may use state machine diagrams to capture dynamic behavior of individual classes or of collaborations of classes.
bankruptcy, acquisition,
merger, … Traded
IPO planned
Delisted trade
trade trade
trade trade
trade trade
trade Buy
Sell Hold
trade trade
trade
trade trade
trade trade
trade Buy
Sell Hold
initial- listing
composite state nested
state
Figure 3-14: Example of composite and nested states for a stock. Compare with Figure 3-12.
Chapter 3 • Modeling and System Specification
131
Below, in Section 3.3, we will use state machine diagrams to describe problem domains when trying to understand and decompose complex problems into basic problems.
3.2.3 UML Object Constraint Language OCL
The UML standard defines Object Constraint Language OCL based on Boolean logic. Instead of using mathematical symbols for operators Table 3-1, OCL uses only ASCII characters which
makes it easier for typing and computer processing. It also makes OCL a bit wordy in places.
OCL is not a standalone language, but an integral part of the UML. An OCL expression needs to be placed within the context of a UML model. In UML diagrams, OCL is primarily used to write
constraints in class diagrams and guard conditions in state and activity diagrams. OCL expressions, known as constraints, are added to state facts about elements of UML diagrams. Any
implementation derived from such a design model must ensure each of the constraints always remains true.
We should keep in mind that for software classes there is no notion of a computation to specify in the sense of having well-defined start and end points. A class is not a program or subroutine.
Rather, any of object’s operations can be invoked at arbitrary times with no specific order. And the state of the object can be an important factor in its behavior, rather than just input-output
relations for the operation. Depending on its state, the object may act differently for the same operation. To specify the effect of an operation on object’s state, we need to be able to describe
the present state of the object which resulted from any previous sequence of operations invoked on it. Since object’s state is captured in its attributes and associations with other objects, OCL
constraints usually relate to these properties of objects.
OCL Syntax
OCL’s syntax is similar to object-oriented languages such as C++ or Java. OCL expressions consist of model elements, constraints, and operators. Model elements include class attributes,
operations, and associations. However, unlike programming languages OCL is a pure specification language, meaning that an OCL expression is guaranteed to be without side effects.
When an OCL expression is evaluated, it simply returns a value. The state of the system will
Figure 3-15: Example of concurrency in states.
Ivan Marsic • Rutgers
University 132
never change because of the evaluation of an OCL expression, even though an OCL expression can be used to specify a state change, such as in a post-condition specification.
OCL has four built-in types: Boolean, Integer, Real, and String. Table 3-2 shows example values and some examples of the operations on the predefined types. These predefined value types are
independent of any object model and are part of the definition of OCL.
The first step is to decide the context, which is the class for which the OCL expression is applicable. Within the given class context, the keyword
self
refers to all instances of the class. Other model elements can be obtained by navigating using the dot notation from the
self
object. Consider the example of the class diagram in Figure 2-13 above. To access the attribute
numOfTrials_
of the class
Controller
, we write
self.numOfTrials_
Due to encapsulation, object attributes frequently must be accessed via accessor methods. Hence, we may need to write
self.getNumOfTrials
. Starting from a given context, we can navigate associations on the class diagram to refer to other
model elements and their properties. The three basic types of navigation are illustrated in Figure 3-16. In the context of
Class_A
, to access its local attribute, we write
self.attribute2
. Similarly, to access instances of a directly associated class we use the name of the opposite
association-end. So to access the set of instances of
Class_B
in Figure 3-16 we write
self.assocAB
. Lastly, to access instances of an indirectly associated class
Class_C
, we write
self.assocAB.assocBC
. We already know that object associations may be individual objects association multiplicity
equals 1 or collections association multiplicity 1. Navigating a one-to-one association yields
Class_A – attribute1
– attribute2 – …
Class_A – attribute1
– attribute2 – …
a
Local attribute
b
Directly related class
c
Indirectly related class
Class_A
Class_B assocBA
assocAB Class_A
Class_B assocBA
assocAB Class_A
Class_B
Class_C assocBA
assocAB assocCB
assocBC Class_A
Class_B
Class_C assocBA
assocAB assocCB
assocBC
Figure 3-16: Three basic types of navigation. Table 3-2: Basic predefined OCL types and operations on them.
Type Values Operations
Boolean true, false and, or, xor, not, implies, if-then-else
Integer 1, 48,
−3, 84967, … ,
+, −, , abs Real 0.5,
3.14159265, 1.e+5
, +, −, , floor
String With more exploration comes more text.
concat, size, substring
Chapter 3 • Modeling and System Specification
133
directly an object. Figure 2-13 shows a single
LockCtrl
assuming that a single lock is controlled by the system. Assuming that this association is named
lockCtrl_
as in Listing 2.2, the navigation
self.lockCtrl_
yields the single object
lockCtrl_ : LockCtrl
. However, if the
Controller
were associated with multiple locks, e.g., on front and backyard doors, then this navigation would yield a collection of two
LockCtrl
objects. OCL specifies three types of collections:
• OCL sets are used to collect the results of navigating immediate associations with one-to-
many multiplicity. •
OCL sequences are used when navigating immediate ordered associations. •
OCL bags are used to accumulate the objects when navigating indirectly related objects. In this case, the same object can show up multiple times in the collection since it was
accessed via different navigation paths.
Notice that in the example in Figure 3-16c, the expression
self.assocAB.assocBC
evaluates to the set of all instances of class
Class_C
objects associated with all instances of class
Class_B
objects that, in turn, are associated with class
Class_A
objects. To distinguish between attributes in classes from collections, OCL uses the dot notation for
accessing attributes and the arrow operator
-
for accessing collections. To access a property of a collection, we write the collection’s name, followed by an arrow
-
, and followed by the name of the property. OCL provides many predefined operations for accessing collections, some of which
are shown in Table 3-3. Constants are unchanging values of one of the predefined OCL types. Operators combine model
elements and constants to form an expression.