UML state machine: Difference between revisions

Content deleted Content added
Rubyuser (talk | contribs)
m typos & highlighting
 
(133 intermediate revisions by 86 users not shown)
Line 1:
{{Short description|State machines and generalizations in UML}}
{{Use American English|date = April 2019}}
{{For|a general introduction|State diagram}}
{{UML diagram types}}
{{Technical|date=September 2009}}
 
'''UML state machine''',<ref name=UML2_2OMG>{{Citecite webbook
|chapter=StateMachines
| title = OMG Unified Modeling Language (OMG UML), Superstructure Version 2.25.1
| author = OMG
|series=[[Object Management Group |OMG]] Document Number formal/2017-12-05
| url = http://www.omg.org/spec/UML/2.2/Superstructure/PDF
|date=December 2017
|date=February 2009}}</ref> known also as '''UML statechart''', is an object-based variant of [[Harel statechart]]<ref name=Harel87>{{Cite web
|publisher=[[Object Management Group]] Standards Development Organization (OMG SDO)
|page=305
| url = httphttps://www.omg.org/spec/UML/2.2/Superstructure5.1/PDF
}}
</ref>
formerly known as '''UML statechart''', is an extension of the [[mathematics|mathematical]] concept of a [[Finite-state machine|finite automaton]] in [[computer science]] applications as expressed in the [[Unified Modeling Language]] (UML) notation.
 
The concepts behind it are about organizing the way a device, computer program, or other (often technical) process works such that an entity or each of its sub-entities is always in exactly one of a number of possible states and where there are well-defined conditional transitions between these states.
 
|date=FebruaryUML 2009}}</ref>state known also as '''UML statechart''',machine is an object-based variant of [[Harel statechart]],<ref name=Harel87>{{Cite web
| title = Statecharts: A Visual Formalism for Complex Systems
| author = Harel, David
| url = http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Statecharts.pdf
|date year =June 20031987}}</ref>
| date = 1987}}</ref> adapted and extended by the [[Unified Modeling Language]]. UML state machines overcome the main limitations of traditional [[finite state machines]] while retaining their main benefits. UML statecharts introduce the new concepts of [[#Hierarchically nested states|hierarchically nested states]] and [[#Orthogonal regions|orthogonal regions]], while extending the notion of [[#Actions and transitions|actions]]. UML state machines have the characteristics of both [[Mealy machine]]s and [[Moore machine]]s. They support [[#Actions and transitions|actions]] that depend on both the state of the system and the triggering [[#Events|event]], as in Mealy machines, as well as [[#Entry and exit actions|entry and exit actions]], which are associated with states rather than transitions, as in Moore machines.
adapted and extended by UML.<ref name=OMG/><ref name=Dru06>D. Drusinsky, [http://www.elsevier.com/wps/find/bookdescription.cws_home/707940/description#description ''Modelling and verification using UML statecharts''], [[Elsevier]], 2006</ref>
The goal of UML state machines is to overcome the main limitations of traditional [[finite-state machine]]s while retaining their main benefits.
| date = 1987}}</ref> adapted and extended by the [[Unified Modeling Language]]. UML state machines overcome the main limitations of traditional [[finite state machines]] while retaining their main benefits. UML statecharts introduce the new concepts of [[#Hierarchically nested states|hierarchically nested states]] and [[#Orthogonal regions|orthogonal regions]], while extending the notion of [[#Actions and transitions|actions]]. UML state machines have the characteristics of both [[Mealy machine]]s and [[Moore machine]]s. They support [[#Actions and transitions|actions]] that depend on both the state of the system and the triggering [[#Events|event]], as in Mealy machines, as well as [[#Entry and exit actions|entry and exit actions]], which are associated with states rather than transitions, as in Moore machines.<ref name=Samek09>{{Cite web
| title = A crash course in UML state machines
| author = OMGSamek, Miro
| url = http://www.embedded.com/design/prototyping-and-development/4008247/A-crash-course-in-UML-state-machines-Part-1
|date=March 2009}}</ref>
 
The term "UML state machine" can refer to two kinds of state machines: ''behavioral state machines'' and ''protocol state machines''.
Behavioral state machines can be used to model the behavior of individual entities (e.g., class instances)., a subsystem, a package, or even an entire system.
Protocol state machines are used to express usage protocols and can be used to specify the legal usage scenarios of classifiers, interfaces, and ports.<ref name=UML2_2/>
 
== Basic state machine concepts ==
Many software systems are [[event-driven programming|event-driven]], which means that they continuously wait for the occurrence of some external or internal '''[[#Events|event]]''' such as a mouse click, a button press, a time tick, or an arrival of a data packet. After recognizing the event, such systems react by performing the appropriate computation that may include manipulating the hardware or generating “soft” events that trigger other internal software components. (That’sThat's why event-driven systems are alternatively called '''reactive systems'''.) Once the event handling is complete, the system goes back to waiting for the next event.
 
The response to an event generally depends on both the type of the event and on the internal '''[[#States|state]]''' of the system and can include a change of state leading to a '''[[#Actions and transitions|state transition]]'''. The pattern of events, states, and state transitions among those states can be abstracted and represented as a '''[[finite -state machine]]''' (FSM).
 
The concept of ana FSM is important in [[event-driven programming]] because it makes the event handling explicitly dependent on both the event-type and on the state of the system. When used correctly, a state machine can drastically cut down the number of execution paths through the code, simplify the conditions tested at each branching point, and simplify the switching between different modes of execution.<ref name=Samek08>
{{Cite book
| last1 = Samek
Line 28 ⟶ 49:
| isbn = 978-0-7506-8706-5
| page = 728}}
</ref>
</ref> Conversely, using event-driven programming without an underlying FSM model can lead programmers to produce error prone, difficult to extend and excessively complex application code.<ref name=Samek03b />
 
=== Basic UML state diagrams ===
Line 36 ⟶ 58:
 
=== Events ===
An '''event''' is something that happens that affects the system.
In the most general terms, an '''event''' is an occurrence in time and space that has significance to the system. Strictly speaking, in the UML specification,<ref name=UML2_2></ref> the term event refers to the type of occurrence rather than to any concrete instance of that occurrence. For example, Keystroke is an event for the keyboard, but each press of a key is not an event but a concrete instance of the Keystroke event. Another event of interest for the keyboard might be Power-on, but turning the power on tomorrow at 10:05:36 will be just an instance of the Power-on event.
Strictly speaking, in the UML specification,<ref name=OMG/>
the term event refers to the type of occurrence rather than to any concrete instance of that occurrence.
In the most general terms, an '''event''' is an occurrence in time and space that has significance to the system. Strictly speaking, in the UML specification,<ref name=UML2_2></ref> the term event refers to the type of occurrence rather than to any concrete instance of that occurrence. For example, Keystroke is an event for the keyboard, but each press of a key is not an event but a concrete instance of the Keystroke event. Another event of interest for the keyboard might be Power-on, but turning the power on tomorrow at 10:05:36 will be just an instance of the Power-on event.
 
An event can have associated '''parameters''', allowing the event instance to convey not only the occurrence of some interesting incident but also quantitative information regarding that occurrence. For example, the Keystroke event generated by pressing a key on a computer keyboard has associated parameters that convey the character scan code as well as the status of the Shift, Ctrl, and Alt keys.
Line 43 ⟶ 68:
 
=== States ===
AEach state machine has a '''state''', captureswhich thegoverns relevant aspectsreaction of the system'sstate historymachine veryto efficientlyevents. For example, when you strike a key on a keyboard, the character code generated will be either an uppercase or a lowercase character, depending on whether the Caps Lock is active. Therefore, the keyboard's behavior can be divided into two states: the "default" state and the "caps_locked" state. (Most keyboards actually haveinclude an LED that indicates that the keyboard is in the "caps_locked" state.) The behavior of a keyboard depends only on certain aspects of its history, namely whether the Caps Lock key has been pressed, but not, for example, on how many and exactly which other keys have been pressed previously. A state can abstract away all possible (but irrelevant) event sequences and capture only the relevant ones.
 
ToIn relatethe this concept to programming, this means that insteadcontext of recordingsoftware thestate eventmachines history(and inespecially aclassical multitude of variablesFSMs), flags,the andterm convoluted''state'' logic,is youoften relyunderstood mainly onas justa onesingle ''state variable'' that can assume only a limited number of a priori determined values (e.g., two values in case of the keyboard, or more generally - some kind of variable with an ''enum'' type in many programming languages). The idea of ''state variable'' (and classical FSM model) is that the value of the ''state variable'' crisplyfully defines the current state of the system at any given time. The concept of the state reduces the problem of identifying the execution context in the code to testing just the state variable instead of many variables, thus eliminating a lot of conditional logic. Moreover, switching between different states is vastly simplified as well, because you need to reassign just one state variable instead of changing multiple variables in a self-consistent manner.
 
=== Extended states ===
OneIn possiblepractice, interpretationhowever, ofinterpreting statethe forwhole softwarestate systemsof is that eachthe state representsmachine oneas distincta setsingle of''state validvariable'' valuesquickly ofbecomes the whole program memory. Evenimpractical for simpleall programsstate withmachines onlybeyond avery fewsimple elementaryones. variablesIndeed, thiseven interpretationif leadswe to an astronomical number of states. For example,have a single 32-bit integer in our machine state, it could contribute to over 4 billion different states. Clearly,- and will lead to a premature ''state explosion''. thisThis interpretation is not practical, so programin variablesUML arestate commonlymachines dissociatedthe fromwhole states.''state'' Rather,of the completestate conditionmachine ofis thecommonly systemsplit into (calleda) thean enumerable ''state variable'' and (b) all the other variables which are named ''extended state'''). Another way to see it is to interpret the combinationenumerable of''state variable'' as a qualitative aspect (and the ''extended state)'' andas the quantitative aspects (of the extendedwhole state variables). In this interpretation, a change of variable does not always imply a change of the qualitative aspects of the system behavior and therefore does not lead to a change of state.<ref name=ROOM94>
{{Cite book
| last1 = Selic
Line 63 ⟶ 88:
</ref>
 
State machines supplemented with ''extended state'' variables are called '''extended state machines''' and UML state machines belong to this category. Extended state machines can apply the underlying formalism to much more complex problems than is practical without including extended state variables. For instanceexample, supposeif thewe behaviorhave ofto theimplement keyboardsome depends on the numberkind of characterslimit typedin onour itFSM so(say, farlimiting andnumber that after, say, 1,000of keystrokes, theon keyboard breaksto down1000), andwithout enters the final''extended state.'' To model this behavior in a state machine without memory, you wouldwe'd need to introducecreate 1,000and statesprocess (e.g.,1000 pressingstates a key in state stroke123 would lead to state stroke124, and so on),- which is clearlynot anpractical; impractical proposition. Alternativelyhowever, you could constructwith an extended state machine withwe can introduce a <code>key_count down-counter</code> variable., Thewhich counter would beis initialized to 1,0001000 and decremented by every keystroke without changing ''state variable''. When the counter reached zero, the state machine would enter the final state.
 
[[Image:UML state machine Fig2.png|thumb|upright=3|center|Figure 2: Extended state machine of "cheap keyboard" with extended state variable key_count and various guard conditions]]
 
The state diagram from Figure 2 is an example of an extended state machine, in which the complete condition of the system (called the ''extended state'') is the combination of a qualitative aspect—the "''state" variable''—and the quantitative aspects—the ''extended state'' variables (such as the down-counter <code>key_count</code>). In extended state machines, a change of a variable does not always imply a change of the qualitative aspects of the system behavior and therefore does not always lead to a change of state.
 
The obvious advantage of extended state machines is flexibility. For example, extendingchanging the lifespanlimit ofgoverned theby "cheap keyboard"<code>key_count</code> from 1,0001000 to 10,00010000 keystrokes, would not complicate the extended state machine at all. The only modification required would be changing the initialization value of the <code>key_count</code> down-counterextended instate thevariable initialduring transitioninitialization.
 
This flexibility of extended state machines comes with a price, however, because of the complex coupling between the "qualitative" and the "quantitative" aspects of the extended state. The coupling occurs through the guard conditions attached to transitions, as shown in Figure 2.
Line 76 ⟶ 101:
'''Guard conditions''' (or simply guards) are [[Boolean function|Boolean expressions]] evaluated dynamically based on the value of [[#Extended states|extended state variables]] and [[#Events|event parameters]]. Guard conditions affect the behavior of a state machine by enabling actions or transitions only when they evaluate to TRUE and disabling them when they evaluate to FALSE. In the UML notation, guard conditions are shown in square brackets (e.g., <code>[key_count == 0]</code> in Figure 2).
 
The need for guards is the immediate consequence of adding memory [[#Extended states|extended state variables]] to the state machine formalism. Used sparingly, extended state variables and guards make up an incrediblya powerful mechanism that can immensely simplify designs. But don’t let the fancy name ("guard") and the concise UML notation fool you. When you actually code an extended state machine, the guards become the same IFs and ELSEs that you wanted to eliminate by using the state machine in the first place. Too many of them, and you’ll find yourself back in square one ("[[spaghetti code]]"), where the guards effectively take over handling of all the relevant conditions in the system.
On the other hand, it is possible to abuse extended states and guards quite easily.<ref name=Samek03d>{{Cite web
 
Indeed, abuse of extended state variables and guards is the primary mechanism of [[Software rot|architectural decay]] in designs based on state machines. Usually, in the day-to-day battle, it seems very tempting, especially to programmers new to state machine formalism, to add yet another extended state variable and yet another guard condition (another IF or an ELSE) rather than to factor out the related behavior into a new qualitative aspect of the system—the state. From experience in the trenches, the likelihood of such an architectural decay is directly proportional to the overhead (actual or perceived) involved in adding or removing states (which relates to the actual strategy used for implementing UML state machines.)
 
One of the main challenges in becoming an effective state machine designer is to develop a sense for which parts of the behavior should be captured as the "qualitative" aspects (the "state") and which elements are better left as the "quantitative" aspects (extended state variables). In general, you should actively look for opportunities to capture the event history (what happened) as the "state" of the system, instead of storing this information in extended state variables. For example, a state machine representing the behavior of a pocket calculator might use an extended state variable <code>DecimalFlag</code> to remember that the user entered the decimal point to avoid entering multiple decimal points in the same number. However, a better solution is to observe that entering a decimal point really leads to a distinct state "entering_the_fractional_part_of_a_number," in which the calculator ignores decimal points. This solution is superior for a number of reasons. The lesser reason is that it eliminates one extended state variable and the need to initialize and test it. The more important reason is that the state-based solution is more robust because the context information is used very locally (only in this particular state) and is discarded as soon as it becomes irrelevant. Once the number is correctly entered, it doesn't really matter for the subsequent operation of the calculator whether that number had a decimal point. The state machine moves on to another state and automatically "forgets" the previous context. The <code>DecimalFlag</code> extended state variable, on the other hand, "lays around" well past the time the information becomes irrelevant (and perhaps outdated!). Worse, you must not forget to reset <code>DecimalFlag</code> before entering another number or the flag will incorrectly indicate that indeed the user once entered the decimal point, but perhaps this happened in the context of the ''previous'' number.
 
Capturing behavior as the quantitative "state" has its disadvantages and limitations, too. First, the state and transition topology in a state machine must be static and fixed at [[compile time]], which can be too limiting and inflexible. Sure, you can easily devise "state machines" that would modify themselves at runtime (this is what often actually happens when you try to recode "[[spaghetti code]]" as a state machine). However, this is like writing [[self-modifying code]], which indeed was done in the early days of programming but was quickly dismissed as a generally bad idea. Consequently, "state" can capture only static aspects of the behavior that are known a priori and are unlikely to change in the future.
 
For example, it's fine to capture the entry of a decimal point in the calculator as a separate state "entering_the_fractional_part_of_a_number," because a number can have only one fractional part, which is both known a priori and is not likely to change in the future. However, implementing the "cheap keyboard" without extended state variables and guard conditions would be practically impossible. This example points to the main weakness of the quantitative "state," which simply cannot store too much information (such as the wide range of keystroke counts). Extended state variables and guards are thus a mechanism for adding extra runtime flexibility to state machines.<ref name=Samek03d>{{Cite web
| title = Back to Basics
| author = Samek, Miro
Line 96 ⟶ 114:
Switching from one state to another is called '''state transition''', and the event that causes it is called the triggering event, or simply the '''trigger'''. In the keyboard example, if the keyboard is in the "default" state when the CapsLock key is pressed, the keyboard will enter the "caps_locked" state. However, if the keyboard is already in the "caps_locked" state, pressing CapsLock will cause a different transition—from the "caps_locked" to the "default" state. In both cases, pressing CapsLock is the triggering event.
 
In [[#Extended states|extended state machines]], a transition can have a [[#Guard conditions|guard]], which means that the transition can "fire" only if the guard evaluates to TRUE. A state can have many transitions in response to the same trigger, as long as they have nonoverlapping guards; however, this situation could create problems in the sequence of evaluation of the guards when the common trigger occurs. The UML specification<ref name=UML2_2OMG/>
intentionally does not stipulate any particular order; rather, UML puts the burden on the designer to devise guards in such a way that the order of their evaluation does not matter. Practically, this means that guard expressions should have no side effects, at least none that would alter evaluation of other guards having the same trigger.
 
=== Run-to-completion execution model ===
All state machine formalisms, including UML state machines, universally assume that a state machine completes processing of each event before it can start processing the next event. This model of execution is called '''[[run to completion']]'', or RTC.
 
In the RTC model, the system processes events in discrete, indivisible RTC steps. New incoming events cannot interrupt the processing of the current event and must be stored (typically in an [[Message queue|event queue]]) until the state machine becomes idle again. These semantics completely avoid any internal concurrency issues within a single state machine. The RTC model also gets around the conceptual problem of processing actions associated with transitions, where the state machine is not in a well-defined state (is between two states) for the duration of the action. During event processing, the system is unresponsive (unobservable), so the ill-defined state during that time has no practical significance.
 
Note, however, that RTC does not mean that a state machine has to monopolize the CPU until the RTC step is complete.<ref name=UML2_2OMG/>
The [[Preemption (computing)|preemption]] restriction only applies to the task context of the state machine that is already busy processing events. In a [[Computer multitasking|multitasking environment]], other tasks (not related to the task context of the busy state machine) can be running, possibly preempting the currently executing state machine. As long as other state machines do not share variables or other resources with each other, there are no [[Thread (computer science)#Concurrency and data structures|concurrency hazards]].
 
The key advantage of RTC processing is simplicity. Its biggest disadvantage is that the responsiveness of a state machine is determined by its longest RTC step. Achieving short RTC steps can often significantly complicate real-time designs.
 
== UML extensions to the traditional FSM formalism ==
Though the [[finite -state machine|traditional FSMs]] are an excellent tool for tackling smaller problems, it's also generally known that they tend to become unmanageable, even for moderately involved systems. Due to the phenomenon known as '''state and transition explosion''', the complexity of a traditional FSM tends to grow much faster than the complexity of the system it describes. This happens because the traditional state machine formalism inflicts repetitions. For example, if you try to represent the behavior of a simple pocket calculator with a traditional FSM, you'll immediately notice that many events (e.g., the Clear or Off button presses) are handled identically in many states. A conventional FSM shown in the figure below, has no means of capturing such a commonality and requires ''repeating'' the same actions and transitions in many states. What's missing in the traditional state machines is the mechanism for factoring out the common behavior in order to share it across many states.
 
[[Image:UML state machine Fig2a.png|thumb|upright=3|center|A pocket calculator (left) and the traditional state machine with multiple transitions Clear and Off (right)]]
 
UML state machines addressesaddress exactly this shortcoming of the conventional FSMs. They provide a number of features for eliminating the repetitions so that the complexity of a UML state machine no longer explodes but tends to faithfully represent the complexity of the reactive system it describes. Obviously, these features are very interesting to software developers, because only they make the whole state machine approach truly applicable to real-life problems.
 
=== Hierarchically nested states ===
The most important innovation of UML state machines over the [[finite state machine|traditional FSMs]] is the introduction of '''hierarchically nested states''' (that is why statecharts are also called '''hierarchical state machines''', or '''HSM'''s).<ref>{{Cite web|url=http://www.accu-usa.org/Slides/samek0311.pdf|title=Hierarchical State Machines - a Fundamentally Important Way of Design|author=Samek, Miro}}</ref> The semantics associated with state nesting are as follows (see Figure 3): If a system is in the nested state, for example "result" (called the '''substate'''), it also (implicitly) is in the surrounding state "on" (called the '''superstate'''). This state machine will attempt to handle any event in the context of the substate, which conceptually is at the lower level of the hierarchy. However, if the substate "result" does not prescribe how to handle the event, the event is not quietly discarded as in a traditional "flat" state machine; rather, it is automatically handled at the higher level context of the superstate "on". This is what is meant by the system being in state "result" as well as "on". Of course, state nesting is not limited to one level only, and the simple rule of event processing applies recursively to any level of nesting.
 
[[Image:UML state machine Fig2b.png|thumb|upright=3|center|Figure 3: A pocket calculator (left) and the UML state machine with state nesting (right)]]
Line 121 ⟶ 141:
States that contain other states are called ''composite states''; conversely, states without internal structure are called ''simple states''. A nested state is called a ''direct substate'' when it is not contained by any other state; otherwise, it is referred to as a ''transitively nested substate''.
 
Because the internal structure of a composite state can be arbitrarily complex, any hierarchical state machine can be viewed as an internal structure of some (higher-level) composite state. It is conceptually convenient to define one composite state as the ultimate root of state machine hierarchy. In the UML specification,<ref name=UML2_2/> every state machine has a '''top stateregion''' (the abstract root of every state machine hierarchy),<ref>{{cite which contains all the other elements of the entire state machine. The graphical rendering of this all-enclosing top state is optional.book
|chapter=Region
|title=Unified Modeling Language 2.5.1
|series=[[Object Management Group |OMG]] Document Number formal/2017-12-05
|date=December 2017
|publisher=[[Object Management Group]] Standards Development Organization (OMG SDO)
|page=352
|url=https://www.omg.org/spec/UML/2.5.1/PDF
}}
</ref> which contains all the other elements of the entire state machine.
The graphical rendering of this all-enclosing region is optional.
 
As you can see, the semantics of hierarchical state decomposition are designed to facilitate reusing of behavior. The substates (nested states) need only define the differences from the superstates (surroundingcontaining states). A substate can easily inherit<ref name=Samek03b>{{Cite web
| title = Who Moved My State?
| author = Samek, Miro
| url = http://www.ddj.com/cpp/184401643
| publisher = C/C++ Users Journal, The Embedded Angle column
|date=April 2003}}</ref> the common behavior from its superstate(s) by simply ignoring commonly handled events, which are then automatically handled by higher-level states. In other words, hierarchical state nesting enables '''[[programming by difference]]'''.<ref name="Samek03c">{{Cite web|author=Samek|first=Miro|date=June 2003|title=Dj Vu|url=http://www.ddj.com/cpp/184401665|archive-url=https://web.archive.org/web/20120930224548/http://www.drdobbs.com/dj-vu/184401665|archive-date=2012-09-30|publisher=C/C++ Users Journal, The Embedded Angle column}}</ref>
| title = Dj Vu
| author = Samek, Miro
| url = http://www.ddj.com/cpp/184401665
| publisher = C/C++ Users Journal, The Embedded Angle column
|date=June 2003}}</ref>
 
The aspect of state hierarchy emphasized most often is [[abstraction]]—an old and powerful technique for coping with complexity. Instead of facingaddressing all aspects of a complex system at the same time, it is often possible to ignore (abstract away) some parts of the system. Hierarchical states are an ideal mechanism for hiding internal details because the designer can easily zoom out or zoom in to hide or show nested states.
 
However, the composite states don't simply hide complexity; they also actively reduce it through the powerful mechanism of hierarchical event processing. Without such reuse, even a moderate increase in system complexity oftencould leadslead to an explosive increase in the number of states and transitions. For example, the hierarchical state machine representing the pocket calculator (Figure 3) avoids repeating the transitions Clear and Off in virtually every state. Avoiding repetitionsrepetition allows the growth of HSMs to growremain proportionallyproportionate to growth in system complexity. As the modeled system grows, the opportunity for reuse also increases and thus potentially counteracts the explosivedisproportionate increase in numbers of states and transitions typical forof traditional FSMs.
 
=== Orthogonal regions ===
HierarchicalAnalysis by hierarchical state decomposition can beinclude viewedthe asapplication of the operation 'exclusive-OR' operationto appliedany togiven statesstate. For example, if a system is in the "on" superstate (Figure 3), it meansmay be the case that it's eitheris also in either "operand1" substate OR the "operand2" substate OR the "opEntered" substate OR the "result" substate. ThatThis iswould lead to description whyof the "on" superstate is calledas an 'OR-state'.
 
UML statecharts also introduce the complementary AND-decomposition. Such decomposition means that a composite state can contain two or more orthogonal regions (orthogonal means compatible and independent in this context) and that being in such a composite state entails being in all its orthogonal regions simultaneously.<ref name=Harel98>
{{Cite book
| last1 = Harel
Line 155 ⟶ 180:
</ref>
 
Orthogonal regions address the frequent problem of a combinatorial increase in the number of states when the behavior of a system is fragmented into independent, concurrently active parts. For example, apart from the main keypad, a computer keyboard has an independent numeric keypad. From the previous discussion, recall the two states of the main keypad already identified: "default" and "caps_locked" (see Figure 1). The numeric keypad also can be in two states—"numbers" and "arrows"—depending on whether Num Lock is active. The complete state space of the keyboard in the standard decomposition is therefore the cross-[[Cartesian product]] of the two components (main keypad and numeric keypad) and consists of four states: "default–numbers," "default–arrows," "caps_locked–numbers," and "caps_locked–arrows." However, this iswould be an unnatural representation because the behavior of the numeric keypad does not depend on the state of the main keypad and vice versa. OrthogonalThe regionsuse allowof youorthogonal toregions avoidallows the mixing theof independent behaviors as a cross-Cartesian product to be avoided and, instead, to keepfor them to remain separate, as shown in Figure 4.
 
[[Image:UML state machine Fig4.png|thumb|upright=3|center|Figure 4: Two orthogonal regions (main keypad and numeric keypad) of a computer keyboard]]
 
Note that if the orthogonal regions are fully independent of each other, their combined complexity is simply additive, which means that the number of independent states needed to model the system is simply the sum ''k + l + m + ...'', where ''k, l, m, ...'' denote numbers of OR-states in each orthogonal region. TheHowever, the general case of mutual dependency, on the other hand, results in multiplicative complexity, so in general, the number of states needed is the product ''k × l × m × ...''.
 
In most real-life situations, however, orthogonal regions arewould be only approximately orthogonal (i.e., theynot are nottruly independent). Therefore, UML statecharts provide a number of ways for orthogonal regions to communicate and synchronize their behaviors. FromAmong these rich sets of (sometimes complex) mechanisms, perhaps the most important feature is that orthogonal regions can coordinate their behaviors by sending event instances to each other.
 
Even though orthogonal regions imply independence of execution (i.e.,allowing somemore kindor ofless concurrency), the UML specification does not require that a separate thread of execution be assigned to each orthogonal region (although itthis can be implementeddone thatif waydesired). In fact, most commonly, orthogonal regions execute within the same thread.<ref name=Douglass99>
{{Cite book
| last1 = Douglass
Line 171 ⟶ 196:
| year = 1999
| isbn = 0-201-49837-5
| page = [https://archive.org/details/doinghardtimedev0000doug/page/749 749]
| page = 749}}
| url = https://archive.org/details/doinghardtimedev0000doug/page/749
</ref> The UML specification only requires that the designer not rely on any particular order in which an event instance will be dispatched to the involved orthogonal regions.
}}
</ref> The UML specification only requires only that the designer does not rely on any particular order in which anfor event instanceinstances willto be dispatched to the involvedrelevant orthogonal regions.
 
=== Entry and exit actions ===
Line 179 ⟶ 206:
[[Image:UML state machine Fig5.png|thumb|upright=3|center|Figure 5: Toaster oven state machine with entry and exit actions]]
 
The value of entry and exit actions is that they provide means for ''guaranteed initialization and cleanup'', very much like class constructors and destructors in OOP[[Object-oriented programming]]. For example, consider the "door_open" state from Figure 5, which corresponds to the toaster oven behavior while the door is open. This state has a very important safety-critical requirement: Always disable the heater when the door is open. Additionally, while the door is open, the internal lamp illuminating the oven should light up.
 
Of course, yousuch behavior could modelbe such behaviormodeled by adding appropriate actions (disabling the heater and turning on the light) to every transition path leading to the "door_open" state (the user may open the door at any time during "baking" or "toasting" or when the oven is not used at all). You alsoIt should not forgetbe forgotten to extinguish the internal lamp with every transition leaving the "door_open" state. However, such a solution would cause the [[Don't repeat yourself|repetition]] of actions in many transitions. More importantimportantly, such an approach isleaves the design error-prone induring viewsubsequent of changesamendments to the state machinebehavior (e.g., the next programmer working on a new feature, such as top-browning, might simply forget to disable the heater on transition to "door_open").
 
Entry and exit actions allow youimplementation to implement theof desired behavior in a much safer, simpler, and more intuitive way. As shown in Figure 5, youit could specifybe specified that the exit action from "heating" disables the heater, the entry action to "door_open" lights up the oven lamp, and the exit action from "door_open" extinguishes the lamp. The use of entry and exit actionactions is superiorpreferable to placing actionsan action on transitionsa transition because it avoids repetitionsrepetitive ofcoding thoseand actionsimproves onfunction transitionsby andeliminating eliminates the basica safety hazard; of leaving the (heater on while the door is open). The semantics of exit actions guarantees that, regardless of the transition path, the heater will be disabled when the toaster is not in the "heating" state.
 
Because entry actions are executed automatically whenever an associated state is entered, they often determine the conditions of operation or the identity of the state, very much as a class constructor determines the identity of the object being constructed. For example, the identity of the "heating" state is determined by the fact that the heater is turned on. This condition must be established before entering any substate of "heating" because entry actions to a substate of "heating," like "toasting," rely on proper initialization of the "heating" superstate and perform only the differences from this initialization. Consequently, the order of execution of entry actions must always proceed from the outermost state to the innermost state (top-down).
Line 190 ⟶ 217:
 
=== Internal transitions ===
Very commonly, an event causes only some internal actions to execute but does not lead to a change of state (state transition). In this case, all actions executed comprise the '''internal transition'''. For example, when youone typetypes on youra keyboard, it responds by generating different character codes. However, unless you hit the Caps Lock key is pressed, the state of the keyboard does not change (no state transition occurs). In UML, this situation should be modeled with internal transitions, as shown in Figure 6. The UML notation for internal transitions follows the general syntax used for exit (or entry) actions, except instead of the word entry (or exit) the internal transition is labeled with the triggering event (e.g., see the internal transition triggered by the ANY_KEY event in Figure 6).
 
[[Image:UML state machine Fig6.png|thumb|upright=3|center|Figure 6: UML state diagram of the keyboard state machine with internal transitions]]
Line 199 ⟶ 226:
 
=== Transition execution sequence ===
State nesting combined with entry and exit actions significantly complicates the state transition semantics in HSMs compared to the traditional FSMs. When dealing with [[#Hierarchically nested states|hierarchically nested states]] and [[#Orthogonal regions|orthogonal regions]], the simple term ''current state'' can be quite confusing. In an HSM, more than one state can be active at once. If the state machine is in a leaf state that is contained in a composite state (which is possibly contained in a higher-level composite state, and so on), all the composite states that either directly or transitively contain the leaf state are also active. Furthermore, because some of the composite states in this hierarchy might have orthogonal regions, the current active state is actually represented by a tree of states starting with the single top stateregion at the root down to individual simple states at the leaves. The UML specification refers to such a state tree as state configuration.<ref name=UML2_2OMG/>
 
[[Image:UML state machine Fig7.png|thumb|upright=3|center|Figure 7: State roles in a state transition]]
 
In UML, a state transition can directly connect any two states. These two states, which may be composite, are designated as the '''main source''' and the '''main target''' of a transition. Figure 7 shows a simple transition example and explains the state roles in that transition. The UML specification prescribes that taking a state transition involves executing the following actions in the following predefined sequence (see Section 1514.2.3.149.6 inof ''OMG Unified Modeling Language (OMG UML), Infrastructure Version 2.2''<ref name=UML2_2OMG/>):
# Evaluate the guard condition associated with the transition and perform the following steps only if the guard evaluates to TRUE.
# Exit the source state configuration.
Line 209 ⟶ 236:
# Enter the target state configuration.
 
The transition sequence is easy to interpret in the simple case of both the main source and the main target nesting at the same level. For example, transition T1 shown in Figure 7 causes the evaluation of the guard g(); followed by the sequence of actions: <code>a(); b(); t(); c(); d();</code> and <code>e()</code>,; assuming that the guard <code>g()</code> evaluates to TRUE.
 
However, in the general case of source and target states nested at different levels of the state hierarchy, it might not be immediately obvious how many levels of nesting need to be exited.
The UML specification<ref name=UML2_2OMG/>
prescribes that a transition involves exiting all nested states from the current active state (which might be a direct or transitive substate of the main source state) up to, but not including, the '''least common ancestor''' (LCA) state of the main source and main target states.
As the name indicates, the LCA is the lowest composite state that is simultaneously a superstate (ancestor) of both the source and the target states. As described before, the order of execution of exit actions is always from the most deeply nested state (the current active state) up the hierarchy to the LCA but without exiting the LCA. For instance, the LCA(s1,s2) of states "s1" and "s2" shown in Figure 7 is state "s."
 
Entering the target state configuration commences from the level where the exit actions left off (i.e., from inside the LCA). As described before, entry actions must be executed starting from the highest-level state down the state hierarchy to the main target state. If the main target state is composite, the UML semantics prescribes to "drill" into its submachine recursively using the local initial transitions. The target state configuration is completely entered only after encountering a leaf state that has no initial transitions.
 
=== Local versus external transitions ===
Before UML 2,<ref name=OMG/>
Before UML 2,<ref name=UML2_2/> the only transition semantics in use was the '''external transition''', in which the main source of the transition is always exited and the main target of the transition is always entered. UML 2 preserved the "external transition" semantics for backward compatibility, but introduced also a new kind of transition called '''local transition''' (see Section 15.3.15 in ''OMG Unified Modeling Language (OMG UML), Infrastructure Version 2.2''<ref name=UML2_2/>). For many transition topologies, external and local transitions are actually identical. However, a local transition doesn’t cause exit from the main source state if the main target state is a substate of the main source. In addition, local state transition doesn’t cause exit and reentry to the target state if the main target is a superstate of the main source state.
the only transition semantics in use was the '''external transition''', in which the main source of the transition is always exited and the main target of the transition is always entered.
UML 2 preserved the "external transition" semantics for backward compatibility, but introduced also a new kind of transition called '''local transition''' (see Section 14.2.3.4.4 of ''Unified Modeling Language (UML)''<ref name=OMG/>).
For many transition topologies, external and local transitions are actually identical. However, a local transition doesn't cause exit from and reentry to the main source state if the main target state is a substate of the main source. In addition, a local state transition doesn't cause exit from and reentry to the main target state if the main target is a superstate of the main source state.
 
[[Image:UML state machine Fig8.png|thumb|upright=3|center|Figure 8: Local (a) versus external transitions (b).]]
 
Figure 8 contrasts local (a) and external (b) transitions. In the top row, you see the case of the main source containing the main target. The local transition does not cause exit from the source, while the external transition causes exit and re-entryreentry to the source. In the bottom row of Figure 8, you see the case of the main target containing the main source. The local transition does not cause entry to the target, whereas the external transition causes exit and reentry to the target.
 
=== Event deferral ===
Sometimes an event arrives at a particularly inconvenient time, when a state machine is in a state that cannot handle the event. In many cases, the nature of the event is such that it can be postponed (within limits) until the system enters another state, in which it is better prepared to handle the original event.
 
UML state machines provide a special mechanism for '''deferring events''' in states. In every state, you can include a clause <code>[event list]/defer</code>. If an event in the current state’sstate's deferred event list occurs, the event will be saved (deferred) for future processing until a state is entered that does not list the event in its deferred event list. Upon entry to such a state, the UML state machine will automatically recall any saved event(s) that are no longer deferred and processwill themthen aseither ifconsume theyor discard these events. It is possible for a superstate to have justa arrivedtransition defined on an event that is deferred by a substate. Consistent with other areas in the specification of UML state machines, the substate takes precedence over the superstate, the event will be deferred and the transition for the superstate will not be executed. In the case of orthogonal regions where one orthogonal region defers an event and another consumes the event, the consumer takes precedence and the event is consumed and not deferred.
 
== The limitations of UML state machines ==
Harel statecharts, which are the precursors of UML state machines, have been invented as "a visual formalism for complex systems",<ref name=Harel87/> so from their inception, they have been inseparably associated with graphical representation in the form of state diagrams.
However, it is important to understand that the concept of UML state machine transcends any particular notation, graphical or textual.
The UML specification<ref name=UML2_2OMG/>
makes this distinction apparent by clearly separating state machine semantics from the notation.
 
However, the notation of UML statecharts is not purely visual. Any nontrivial state machine requires a large amount of textual information (e.g., the specification of actions and guards). The exact syntax of action and guard expressions isn’tisn't defined in the UML specification, so many people use either structured English or, more formally, expressions in an implementation language such as [[C (programming language)|C]], [[C++]], or [[Java (programming language)|Java]].<ref name=Douglass99b>{{Cite web
| title = UML Statecharts
| author = Douglass, Bruce Powel
| url = httphttps://www.embedded.com/1999design/9901uml/9901feat1.htm4219602/UML-Statecharts
| publisher = Embedded Systems Programming
|date=January 1999}}</ref> In practice, this means that UML statechart notation depends heavily on the specific [[programming language]].
 
Nevertheless, most of the statecharts semantics are heavily biased toward graphical notation. For example, state diagrams poorly represent the sequence of processing, be it order of evaluation of [[#Guard conditions|guards]] or order of dispatching events to [[#Orthogonal regions|orthogonal regions]]. The UML specification sidesteps these problems by putting the burden on the designer not to rely on any particular sequencing. ButHowever, whenit youis actuallythe implementcase that when UML state machines, youare actually implemented, willthere alwaysis haveinevitably full control over the order of execution, sogiving therise restrictionsto imposedcriticism bythat the UML semantics willmay be unnecessarily restrictive. Similarly, statechart diagrams require a lot of plumbing gear (pseudostates, like joins, forks, junctions, choicepoints, etc.) to represent the flow of control graphically. These elements are essentially the old [[flowchart]] in disguise, which structured programming techniques proved far less significant a long time ago. In other words, these elements of the graphical notation do not add much value in representing flow of control as compared to plain [[Structured programming|structured code]].
 
The UML notation and semantics are really geared toward computerized [[UML tools]]. A UML state machine, as represented in a tool, is not just the state diagram, but rather a mixture of graphical and textual representation that precisely captures both the state topology and the actions. The users of the tool can get several complementary views of the same state machine, both visual and textual, whereas the generated code is just one of the many available views.
Line 243 ⟶ 279:
== References ==
{{Reflist}}
 
== External links ==
 
* {{cite book
|title=Unified Modeling Language 2.5.1
|series=[[Object Management Group |OMG]] Document Number formal/2017-12-05
|date=December 2017
|publisher=[[Object Management Group]] Standards Development Organization (OMG SDO)
|url=https://www.omg.org/spec/UML/2.5.1/PDF
}}
 
* [http://www.uml-diagrams.org/state-machine-diagrams.html UML 2 State Machine Diagrams]
 
{{Formal languages and grammars}}
{{UML}}
 
[[Category:Automata theory(computation)]]
<!-- [[UML state machine]] -->
[[Category:Models of computation]]
 
{{DEFAULTSORT:Uml State Machine}}
[[Category:Automata theory]]
[[Category:Computational models]]
[[Category:Digital electronics]]
[[Category:Formal methods]]
[[Category:UMLUnified Modeling Language diagrams]]
 
[[de:Zustandsdiagramm (UML)]]
[[ru:Диаграмма автомата]]