Analysis: Defining Object Behavior
Chapter 6 showed how to define the system structure by identifying the fundamental objects and classes and their relationships. In this chapter, we define and refine operations and behaviors. There are a number of means for specifying overall object behavior, the most important of these being modeling the object as a finite state machine. Scenario modeling helps you test your behavioral models to ensure that the objects can collaborate to achieve the system responsibilities. The state and scenario models lead to the definitions of class operations required to process the incoming messages and events.
Notation and Concepts Discussed |
||
---|---|---|
Simple Behavior |
Or-state |
Action |
Continuous Behavior |
And-state |
Pseudostate |
State Behavior |
Event |
Statechart |
State |
Transition |
Operation |
7.1 Object Behavior
Chapter 6 presented the analysis and decomposition of systems into their object structure and relationships. The other pillar of object-oriented analysis is the specification of dynamic behavior. Behavior binds the structure of objects to their attributes and relationships so that objects can meet their responsibilities. Ultimately, an object's operations implement its behavior. There are means for constraining and controlling these primitive operations into permissible sequences. The most important of these is the finite state machine. The behavioral notations and semantics of the UML were introduced in Chapter 3; this chapter focuses on how to effectively apply these notations and semantics to solve our real-world problems.
7.1.1 Simple Behavior
We define three types of behavior: simple, state, and continuous. The object with simple behavior performs services on request and keeps no memory of previous services. A simple object always responds to a given input in exactly the same way regardless of its history. Some examples of simple behaviors are
-
Simple mathematical functions, such as cosine or square root
-
A search operation of a static data structure that always starts from the same point, such as the search of a static binary tree
-
Sort operations
-
A knob that returns the number of clicks for a given user action
For example,
returns the same value regardless of what value can call the COS() function with previously. In other cases, the distinction is not as clear. Is the search of a binary tree simple or state-driven? If the behavior changes due to previous input, then it cannot by definition be simple. If the binary tree provides methods like next() and previous(), then it must maintain an internal state between calls. If the tree only provides calls such as find(), then at least to its clients it exhibits stateless behavior.
Activity diagrams provide token-flow semantics. That is, an activity is decomposed into subactivities, until at the bottom we find actions. Actions execute when they receive a control token from each of their predecessor activities. In the case of simple sequential actions within an activity, this is just a statement that an activity (or action) begins to execute when the activity (or action) that comes before it completes. In the case of concurrency, an activity (or action) can have multiple predecessors, and so must receive a control token from every one of its predecessors before it is allowed to execute.
Figure 7-1 shows an activity diagram for computing net worth. The forks and joins show activities that may be allowed to execute in parallel. Token flow semantics are simple to explain in the figure:
-
For a sequential flow (simple arrow between lines) a control token is passed when the previous activity completes; the subsequent activity begins once it receives the control token.
-
For a fork, a control token is passed to every subsequent activity, meaning that they are all free to execute, and the order of execution of its concurrent peer activities is not defined.
-
For a join, a control token must be passed by every predecessor activity before the subsequent activity is allowed to run. Thus, all of the following activities must complete before the "print Assets" activity is allowed to run:
-
Assets += Get Property Assets
-
Assets += Get Bank Assets
-
Assets += Get Investment Assets
-
-
For branches (the diamond), only a single control token is passed. The active branch is selected on the basis of guard conditions; if a guard is TRUE then that branch may be passed the control token when the predecessor activity completes. If multiple guards evaluate to TRUE, then any of the true branches may be selected, but only one will receive the control token (however, it is impossible to say which one will be selected).
Figure 7-1. Token-Flow Semantics
7.1.2 State Behavior
The second type of object behavior is called state, state-driven, or reactive. Our definition of a state is as follows:
A state is an ontological condition that persists for a significant period of time that is distinguishable from other such conditions and is disjoint from them. A distinguishable state means that it differs from other states in the events it accepts, the transitions it takes as a result of accepting those events, or the actions it performs. A transition is a response to an event that causes a change in state.
Modeling an object as a finite state machine (FSM) attempts to reduce the behavioral complexity by making some simplifying assumption. Specifically, it assumes the following:
-
The system being modeled can assume only a finite number of existence conditions, called states.
-
The system behavior within a given state is essentially identical and is defined by
-
The messages and events accepted
-
The actions associated entering or leaving the state
-
The activities performed while in the state
-
The reachability graph of subsequent states
-
The complete set of transition-target state pairs
-
-
The system resides in states for significant periods of time.
-
The system may change these conditions only in a finite number of well-defined ways, called transitions.
-
Transitions run to completion, including the action execution, whether they are associated directly with the transition itself, or entry or exit actions for the state entered or exited.
The set of all possible behaviors of an object is bounded by the set of operations defined on the object. An FSM adds constraints regarding when and under what conditions those operations will execute.
7.1.3 Continuous Behavior
The third kind of object behavior is called continuous. Many objects show continuous behavior, including digital filters and PID1 control loops. All that is required is that the current output depend on the previous history in a smooth way. An object with continuous behavior is one with an infinite, or at least unbounded, set of existence conditions. PID control systems, fuzzy sets, and neural networks all display continuous behavior.
The UML is very expressly a discrete modeling language, and provides no direct means for modeling continuous system behavior.2 However, many kinds of continuous behavior can be defined using token flow semantics. This is normally done by expressing the algorithm as difference equations (derived from the differential equations). Thus, activity diagrams can be used to express behavior that is continuous in value but discrete in execution. A PID control loop, for example, implemented with a difference equation, is executed periodically, and the object uses attributes to remember the previous value(s) necessary for the computations. However, activity diagrams cannot, without extension, model behavior that is continuous in time, such as the continuously executing mixing of gases, or combustion of fuel. It is often sufficient to use a difference equation approach for the behavioral modeling, but not always.
It is even sometimes appropriate to mix state and continuous behavior. For example, different sets of trajectory differential equations may be used, depending on whether a spacecraft is undergoing launch, achieving orbit, in orbit, or cruising. The sets of equations used in this case depend on the state (in this case, phase of flight) of the trajectory object. This is accomplished by modeling the overall behavior of the object as a state machine; the set of difference or differential equations is modeled as a "do activity" within the states. As the object enters a new state, a different set of differential equations governs the execution of the activity within the state.
Since the UML relies so heavily on finite state machines to represent discrete behavior, let's now explore what than means in more detail.