This example
demonstrates how hierarchical state structure
alows to economize on the state machine
description and simplify implementation of
behavior of this simple
application. Let’s consider an abstract oven. At
the highest level of abstraction (lowest level
of detail) it can be considered to be “On” or
“Off”. However, it is a dual mode oven: when
“On” it can be either “Baking” or “Grilling”.
Naturally, we want the oven to turn the heater
on whenever it goes into the “On” state and turn
it off whenever the oven is not on. Well, every
oven has a door. We will want to turn the light
on whenever we open the door and turn it off
whenever we close it. (The door doesn’t have a
window, so we don’t need the light when it’s
closed.) If we open the door while the oven is
“On” and then close the door we expect the oven
to return to its business, whatever it had been
before we opened the door, i.e. either “Baking”
or “Grilling”. This functionality requires
introduction of one more state, “Paused”, which
will be positioned on the same hierarchy level
as “On” and “Off”. We definitely don’t want the
oven to turn on if the door is opened, so we
have to break the “Off” state into “Off with
Closed Door” and “Off with Opened Door”. The
events that need to be processed (in addition to
the ubiquitous “Exit Requested”, which is
present in any application): “Stop button
pushed”, “Bake button pushed”, “Grill button
pushed”, “Door opened”, “Door closed”. Actions:
“Turn the heater on”, “Turn the heater off”,
“Turn the light On”, “Turn the light off”,
“Close Application”. The resulting statechart/HSM
is shown in the next picture:
It’s conceptually convenient
to define one composite state, top state, as the
root of the state machine hierarchy (Initial and
Final pseudo states can be excluded, though).
This simple example demonstrates in several ways
how exactly HSM eliminates repetition.
If we don’t define the
exit transition from the top state but we
want the system to exit whenever requested,
we will need to explicitly create
transitions to the final state from every
other state.
Note that for the “Stop
Button Pushed” and “Door Opened” events we
need only define one transition each—from
the more general “On” state rather than
individually from “Baking” and “Grilling”.
Thanks to assigning “Turn
Heater On” and Turn Heater Off” as entry and
exit actions, respectively, for the “On”
state, we avoid the need to include them
into every transition into and from the
“Baking” and “Grilling” states.
HSM Semantics can be
extended to include non-overriding behavior
inheritance between states. It means that
the substate can inherit the transition
actions for some event from its superstate
not only when it doesn’t have them within
itself, but also even when it already has a
transition defined for that event. In the
latter case, unless override is chosen, the
actions assigned to an event in the
superstates will be added to the list of
actions assigned in the substate. The actual
target state for the transition will be the
one defined in the substate. The notation in
top left corner of the “Top State” indicates
that the “Turn Light On” action must be
executed whenever the event “Door Opened”
happens and the “Turn Light Off” action must
be executed whenever the event “Door Closed”
happens, regardless of the actual state of
the oven (it is always in the “Top State” ).
Please take a look at the
transition from the “Paused” state on the
“Door Closed” Event. It ends not at the “On”
state, but at a circle with letter “H” in
it. This is a “To History” type of
transition. The circle with the letter “H”
denotes a shallow-history pseudostate. It
means that the actual target state of the
transition will be the most recent active
direct substate of the state containing this
pseudostate. If it were not for this HSM
feature, we would have to define states like
“Paused while Baking” and “Paused while
Grilling” to be able to return the oven to
the state it was in before the door was
opened.