|
|
<!--- **TODO**: Show representation of entry, do, exit and explain usage. Add abort state. -->
|
|
|
|
|
|
**Sources:**
|
|
|
|
|
|
- http://www.omg.org/spec/UML/2.5 (Starting at PDF page 345)
|
|
|
- Transition notation: Starting at PDF page 371
|
|
|
- Trigger specification (including when/after/at): Starting at PDF page 333
|
|
|
|
|
|
# Introduction / Usage Scenarios
|
|
|
|
|
|
The **state machine diagram** is used to illustrate the lifecycle of single objects and the behavior of operations within a software system.
|
|
|
This graph-based diagram can be greatly used to get a detailed understanding of the behavior of objects, conditions and flows within the overall system.
|
|
|
For example, you can use it in the early design phase of a new software system to model the behavior of a specific component to describe its workflow.
|
... | ... | @@ -13,77 +15,82 @@ Especially, when the behavior of an object (lifecycle) or operation is not well |
|
|
|
|
|
UML state diagrams use the following notations:
|
|
|
|
|
|
- *States* are denoted as rectangles with rounded corners and a name.
|
|
|
"A State models a situation in the execution [...] during which some invariant condition holds.
|
|
|
In most cases this condition is not explicitly defined, but is implied, usually through the name associated with the State." (UML Spec 2.5, S.348/306)
|
|
|
For example: "Ringing" or "Dialing" are common states when modeling the state machine for a telephone. *States* may contain (optional) internal behavior that is sequentially executed after entering the state:
|
|
|
|
|
|
- *Entry* actions are executed and completed when the *state* has been entered.
|
|
|
- *Do* actions are executed when the *state* has been entered and always after a potential *entry* action is completed.
|
|
|
*Do* actions are executed until they are completed or until the *state* is left.
|
|
|
Therefore, their execution may be interrupted.
|
|
|
- *Exit* actions are executed right before leaving the *state*, but after potential *entry* and *do* actions.
|
|
|
In contrast to *do* actions, *exit* actions are always completely executed.
|
|
|
|
|
|
- *Transitions* are denoted with a solid line and an open arrow.
|
|
|
As the name implies, they are used to define state transitions.
|
|
|
They may be additionally denoted with a label in the form of `trigger[guard]/effect`.
|
|
|
*Guards* are boolean expressions, which may secure that a *transition* is executed, e.g., "[time left]".
|
|
|
*Effects* are actions, which may be performed if the *transition* is actually executed, e.g., "/go to cinema".
|
|
|
*Triggers* are events, which initially cause the *transition* to be executed.
|
|
|
If no *trigger* is stated, *transitions* are immediately executed upon exiting the state.
|
|
|
There are different types of events for a *trigger*:
|
|
|
- *Call Events* are used "for messages requesting that a specific operation is called", e.g., "work" or "pause".
|
|
|
- *Signal Events* are used to show that a transition is triggered due to a receiving signal, e.g., "lecture started".
|
|
|
- *Change Events* are always denoted by "when" followed by a boolean expression.
|
|
|
They are used to trigger a transition, if an attribute in the current state changed it's value, e.g., "when (money < 0)".
|
|
|
- *Time Events* are denoted with "after" followed by a time expression, e.g., "after (10 seconds)" or "after (lunch)".
|
|
|
Alternatively, *time events* may also express precise instances of time, e.g., "at (Feb. 02, 2018)".
|
|
|
- *Any Receive Events* are always denoted by a simple "all" and are used as fallback or else clause (transition).
|
|
|
|
|
|
- *Composite states* are also denoted as rectangles with rounded corners and a name.
|
|
|
They contain at least one *region*, i.e., a fragment that may execute concurrently with other *regions*.
|
|
|
If you use multiple *regions*, add a note to the *composite state* and declare if the *regions* are executed concurrently or sequentially (if latter, state the specific order of execution).
|
|
|
*Regions* do not contain *transitions* to other *regions*.
|
|
|
A single *region* in a composite state is not visible.
|
|
|
Two or more *regions* are denoted by using dashed lines.
|
|
|
These *regions* (or a single one) are then made up of nested *states* (called *substates*) and *transitions* (both denoted as previously introduced and see example below).
|
|
|
Altogether, *composite states* are used to show hierarchies of states and concurrent execution/behavior.
|
|
|
|
|
|
- *Initial pseudostates* constitute the entry points of the overall state machine or an embedded *region*.
|
|
|
They are denoted with a small solid filled circle.
|
|
|
At one level of hierarchy, there is at most one *initial pseudostate*.
|
|
|
*Transitions* from the *initial pseudostate* are never (!) denoted with a *trigger* or *guard*.
|
|
|
|
|
|
- *Final states* are denoted with a circle surrounding a small solid filled circle.
|
|
|
One level of hierarchy (e.g. *region*) may contain any number of *final states*.
|
|
|
The execution of the state machine level is finished, if a *final state* on the same level is reached.
|
|
|
|
|
|
- *Terminate pseudostates* are denoted with a cross.
|
|
|
One level of hierarchy (e.g. *region*) may contain any number of *terminate pseudostates*.
|
|
|
The overall execution of the state machine is discontinued, if one *terminate pseudostates* at any level is reached.
|
|
|
|
|
|
- *Choice pseudostates* a denoted as diamond-shaped symbols.
|
|
|
*Choice pseudostates* may have multiple (at least two) outgoing *transitions*.
|
|
|
"If a *choice pseudostate* is reached with multiple outgoing *transitions* with *guards*, a *transition* whose *guard* evaluates to true will be taken.
|
|
|
If more than one *guard* evaluates to true, one of these *transitions* is chosen for continuing the
|
|
|
traversal.
|
|
|
The algorithm for making this selection is undefined.
|
|
|
If no guards evaluate to true when the *choice pseudostate* is reached, the model is ill formed" and requires rework.
|
|
|
- _States_ are denoted as rectangles with rounded corners and a name.
|
|
|
"A State models a situation in the execution [...] during which some invariant condition holds.
|
|
|
In most cases this condition is not explicitly defined, but is implied, usually through the name associated with the State." (UML Spec 2.5, S.348/306)
|
|
|
For example: "Ringing" or "Dialing" are common states when modeling the state machine for a telephone. _States_ may contain (optional) internal behavior that is sequentially executed after entering the state:
|
|
|
|
|
|
- _Entry_ actions are executed and completed when the _state_ has been entered.
|
|
|
- _Do_ actions are executed when the _state_ has been entered and always after a potential _entry_ action is completed.
|
|
|
_Do_ actions are executed until they are completed or until the _state_ is left.
|
|
|
Therefore, their execution may be interrupted.
|
|
|
- _Exit_ actions are executed right before leaving the _state_, but after potential _entry_ and _do_ actions.
|
|
|
In contrast to _do_ actions, _exit_ actions are always completely executed.
|
|
|
|
|
|
- _Transitions_ are denoted with a solid line and an open arrow.
|
|
|
As the name implies, they are used to define state transitions.
|
|
|
They may be additionally denoted with a label in the form of `trigger[guard]/effect`.
|
|
|
_Guards_ are boolean expressions, which may secure that a _transition_ is executed, e.g., "[time left]".
|
|
|
_Effects_ are actions, which may be performed if the _transition_ is actually executed, e.g., "/go to cinema".
|
|
|
_Triggers_ are events, which initially cause the _transition_ to be executed.
|
|
|
If no _trigger_ is stated, _transitions_ are immediately executed upon exiting the state.
|
|
|
There are different types of events for a _trigger_:
|
|
|
|
|
|
- _Call Events_ are used "for messages requesting that a specific operation is called", e.g., "work" or "pause".
|
|
|
- _Signal Events_ are used to show that a transition is triggered due to a receiving signal, e.g., "lecture started".
|
|
|
- _Change Events_ are always denoted by "when" followed by a boolean expression.
|
|
|
They are used to trigger a transition, if an attribute in the current state changed it's value, e.g., "when (money < 0)".
|
|
|
- _Time Events_ are denoted with "after" followed by a time expression, e.g., "after (10 seconds)" or "after (lunch)".
|
|
|
Alternatively, _time events_ may also express precise instances of time, e.g., "at (Feb. 02, 2018)".
|
|
|
- _Any Receive Events_ are always denoted by a simple "all" and are used as fallback or else clause (transition).
|
|
|
|
|
|
- _Composite states_ are also denoted as rectangles with rounded corners and a name.
|
|
|
They contain at least one _region_, i.e., a fragment that may execute concurrently with other _regions_.
|
|
|
If you use multiple _regions_, add a note to the _composite state_ and declare if the _regions_ are executed concurrently or sequentially (if latter, state the specific order of execution).
|
|
|
_Regions_ do not contain _transitions_ to other _regions_.
|
|
|
A single _region_ in a composite state is not visible.
|
|
|
Two or more _regions_ are denoted by using dashed lines.
|
|
|
These _regions_ (or a single one) are then made up of nested _states_ (called _substates_) and _transitions_ (both denoted as previously introduced and see example below).
|
|
|
Altogether, _composite states_ are used to show hierarchies of states and concurrent execution/behavior.
|
|
|
|
|
|
- _Initial pseudostates_ constitute the entry points of the overall state machine or an embedded _region_.
|
|
|
They are denoted with a small solid filled circle.
|
|
|
At one level of hierarchy, there is at most one _initial pseudostate_.
|
|
|
_Transitions_ from the _initial pseudostate_ are never (!) denoted with a _trigger_ or _guard_.
|
|
|
|
|
|
- _Final states_ are denoted with a circle surrounding a small solid filled circle.
|
|
|
One level of hierarchy (e.g. _region_) may contain any number of _final states_.
|
|
|
The execution of the state machine level is finished, if a _final state_ on the same level is reached.
|
|
|
|
|
|
- _Terminate pseudostates_ are denoted with a cross.
|
|
|
One level of hierarchy (e.g. _region_) may contain any number of _terminate pseudostates_.
|
|
|
The overall execution of the state machine is discontinued, if one _terminate pseudostates_ at any level is reached.
|
|
|
|
|
|
- _Choice pseudostates_ a denoted as diamond-shaped symbols.
|
|
|
_Choice pseudostates_ may have multiple (at least two) outgoing _transitions_.
|
|
|
"If a _choice pseudostate_ is reached with multiple outgoing _transitions_ with _guards_, a _transition_ whose _guard_ evaluates to true will be taken.
|
|
|
If more than one _guard_ evaluates to true, one of these _transitions_ is chosen for continuing the
|
|
|
traversal.
|
|
|
The algorithm for making this selection is undefined.
|
|
|
If no guards evaluate to true when the _choice pseudostate_ is reached, the model is ill formed" and requires rework.
|
|
|
|
|
|
# Obligations for the lectures and the final exam in "Softwaretechnik" (Tips for Modeling)
|
|
|
|
|
|
When creating a **state machine diagram**, remember that it must contain all necessary information (e.g. states, transitions, triggers, guards and effects).
|
|
|
Especially for transitions between states it is important to specify the relevant triggers, guards, and behaviors.
|
|
|
An example class diagram is shown in [Example State Machine Diagram](#an-example-state-machine-diagram-for-the-given-scenario).
|
|
|
|
|
|
# What is a State?
|
|
|
|
|
|
Consider a state as a specific position within the lifecycle or behavior of an object during runtime of an application.
|
|
|
|
|
|
# Example Scenario
|
|
|
|
|
|
Assume that your customer wants you to develop a banking machine application called "ATM". It acts similar to general ATMs and thus allows to withdraw or to deposit cash. The application has two major states (Authentication or Withdrawal of Cash).
|
|
|
The application starts with Authentication, presents a login screen (openLogin), continues by allowing the user to enter a pin, which is checked afterwards (checkPin), and closes the login screen at the end (closeLogin). Depending on the result of the check (correct or incorrect), the number of unsuccessful tries (errorCounter), and the number of maximum tires (maxTries), the machine may change its state to another state.
|
|
|
The application starts with Authentication, presents a login screen (openLogin), continues by allowing the user to enter a pin, which is checked afterwards (checkPin), and closes the login screen at the end (closeLogin). Depending on the result of the check (correct or incorrect), the number of unsuccessful tries (errorCounter), and the number of maximum tires (maxTries), the machine may change its state to another state.
|
|
|
|
|
|
Possible results are:
|
|
|
|
|
|
- Option 1: incorrect (pin) and errorCounter < maxTries --> try again.
|
|
|
- Option 2: incorrect (pin) and errorCounter >= maxTries --> authentication failed, abort the machine.
|
|
|
- Option 3: correct (pin) --> change to Withdrawal
|
... | ... | @@ -91,22 +98,24 @@ Possible results are: |
|
|
During the withdrawal, the user is able to choose between withdraw and deposit. In both cases he has to define an amount. Depending on the choice, either the specified amount is added to the account or, if the amount does not exceed the balance, subtracted from the account. Afterwards the user is able to finish the transaction (abort of the machine).
|
|
|
|
|
|
## An Example State Machine Diagram for the given Scenario
|
|
|
The following figure shows an example UML state machine diagram, which reflects the requirements mentioned in [Example Scenario](#example-scenario):
|
|
|
|
|
|
The following figure shows an example UML state machine diagram, which reflects the requirements mentioned in [Example Scenario](#example-scenario):
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|
### Explanation
|
|
|
|
|
|
We model the states at first. We identify the two major states Authentication and WithdrawCash, and add two states Rejected, and Finished, in order to provide feedback for the user, instead of aborting the machine directly afterwards.
|
|
|
Additionally, there are two special states (initial state / start - circle completely filled in black, final state / stop - white circle with a black circle in the middle), which are used as an entry and exit for the overall machine. We included the identified states within a parent state ATM, which is started and aborted outside and communicates with the states within.
|
|
|
|
|
|
As described in the scenario, for the Authentication, we have three activities - starting with openLogin, performing checkPin, and finishing with closeLogin. These are modeled as entry, do, and, exit actions within the state. Afterwards, we take a look into the possible results for the pin entry and create the transitions between the states.
|
|
|
|
|
|
Possible results were:
|
|
|
|
|
|
- Option 1: incorrect (pin) and errorCounter < maxTries --> try again, no state change.
|
|
|
- Option 2: incorrect (pin) and errorCounter >= maxTries --> authentication failed, change to state Rejected (abort of the machine).
|
|
|
- Option 3: correct (pin) --> change to state WithdrawCash
|
|
|
|
|
|
Based on this options, we define corresponding transitions, which may lead from our starting state to a different state.
|
|
|
If we take option 1, we need to define a change-Event, which is triggered when the pin is incorrect and errorCounter < maxTries. The action increased the error counter and the user is able to try it again. Otherwise, if the pin is correct, we change the state to WithdrawCash.
|
|
|
Within this state, we have three options - withdraw, deposit, and finish. The transitions are handled in the same way as in the state Authentication, except for the usage of the guard [amount <= balance], which condition needs to be true, otherwise the transition is not executed. In case of a failed authentication, we change towards the Rejected state and may present the user and information about the rejection. The same applies for finishing the WithdrawCash state. Both states lead directly into the final state without any events or guards. |
|
|
\ No newline at end of file |
|
|
Within this state, we have three options - withdraw, deposit, and finish. The transitions are handled in the same way as in the state Authentication, except for the usage of the guard [amount <= balance], which condition needs to be true, otherwise the transition is not executed. In case of a failed authentication, we change towards the Rejected state and may present the user and information about the rejection. The same applies for finishing the WithdrawCash state. Both states lead directly into the final state without any events or guards. |