state pattern in UML

90 views
Skip to first unread message

chihwah li

unread,
May 4, 2012, 9:32:08 AM5/4/12
to UML Forum

Hello,

Could someone shine some light on the following:
How can I show the state pattern in a UML sequence diagram?

UML student question:
My idea so far is: In the lifeline you do an self call and call the
method to
change it's state. Is it nessecary to show all states? Someone wanted
display the different states as "instances" with it's own lifeline. My
thought is: it's not an instance, it's an state. This last thing would
be wrong I guess.
Right?

Many thanks!

Thomas Mercer-Hursh, Ph.D.

unread,
May 4, 2012, 12:09:31 PM5/4/12
to umlf...@googlegroups.com, chihwah li
With a state chart?

H. S. Lahman

unread,
May 4, 2012, 12:28:21 PM5/4/12
to umlf...@googlegroups.com
Responding to li...

>
> Could someone shine some light on the following:
> How can I show the state pattern in a UML sequence diagram?

The short answer is: exactly the same way you would show any other
object collaborations.

The parent State class defines a suite of actions that each subclass
implements differently. Those actions are invoked in collaboration just
like any other object's actions in an SD. One swimlane is the object
sending the message and the other is the State object receiving it.

The State pattern is described in the Class diagram as a generalization,
so one has a choice of whether the receiver swimlane is the superclass
(polymporphic dispatch) or one of the concrete subclasses (the client
only collaborates with a particular substate). This is exactly the same
as one would represent a collaboration with any generalization object.

>
> UML student question:
> My idea so far is: In the lifeline you do an self call and call the
> method to
> change it's state. Is it nessecary to show all states? Someone wanted
> display the different states as "instances" with it's own lifeline. My
> thought is: it's not an instance, it's an state. This last thing would
> be wrong I guess.
> Right?

Not exactly. In the GoF State pattern the point of changeState() is to
dynamically assign what concrete implementation should respond to
message. That essentially dynamically instantiates the relationship that
the client navigates to send a message to a state. (That's what Handle()
does in the GoF example -- it provides the right implementation for the
current solution context.) So changing the state is independent of the
individual collaborations the client has with the State's actions.

In fact, it is usually some other object entirely that invoked
changeState() to prepare the context. That interaction would also appear
on the SD as an object-to-object collaboration. However, it would be
with the Context object rather than a State object. (In the GoF
implementation example, changeState() returns a handle to the right
concrete State and the client then invokes the action through that
handle. Effectively Handle is instantiating a temporary relationship
between the client and the concrete state.)

Having said all that, my general reaction to using the GoF State pattern
to model state machines is: Don't Do That! IMO the pattern is misnamed
and and it really should be named "Role" because that is what it is most
useful for modeling. Thus one might have

<pre>
[Customer]
| *
|
| A1
|
| interacts with
| 1
[Employee] // Context
| *
|
| A2
|
| plays
| 1
[Role] // State
A
| A3
+----------+-----...
| |
[SalesClerk] [Manager]
</pre>

Note that the same employee might perform all the roles (e.g., in a
Ma&Pa store). The appropriate role and activities are determined by the
current context of interaction (sale, complaint, etc.) and that
dynamically determines how the A2 association gets instantiated (i.e.,
changeRole()).

Using the GoF State pattern to represent object states machines is a bad
idea for several reasons. The big one is that it introduces substantial
code bloat because each state must have its own class defined, which is
completely unnecessary. Aesthetically, there is a big problem because
states in state machines should not have multiple actions. [In the
underlying finite state automata, a state has a single action that
processes the incoming event message (alphabet) exactly the same way.]
There is also a minor efficiency problem because of the indirection
though Handle(). It is just an awkward and counterintuitive way to
implement object state machines that way. Finally, the primary reason
for using state machines in the first place is to support the more
general asynchronous communication model for collaborations. IOW, the
synchronous GoF model is kind of an oxymoron for state machines

--
Life is the only flaw in an otherwise perfect nonexistence
-- Schopenhauer

Rene Descartes went into a bar. The bartender asked if he would like a drink. Descartes said, "I think not," and disappeared.

H. S. Lahman
H.la...@verizon.net
software blog: http://pathfinderpeople.blogs.com/hslahman/index.html

Dan George

unread,
May 6, 2012, 12:37:33 PM5/6/12
to umlf...@googlegroups.com
H.S., your comment about a state having only one action could use a little more explanation.

I'll try but I really recommend you all get Lahman's book. The state action is performed upon entry to the state. Thus, there can be only one action and it must always be the same. If a different action is needed then, by definition, the object must enter a different state. The UML and various other state machine notations allow more expressive syntax but the expressive syntax tends to be a crutch. Sticking to the bare-bones FSA notation makes it more difficult to solve structural problems with dynamic solutions. If your state chart is getting complicated, don't switch to a more compact syntax; fix the structural problems that are causing the dynamic complexity.

Dan

H. S. Lahman

unread,
May 7, 2012, 11:10:06 AM5/7/12
to umlf...@googlegroups.com
Responding to George...

> H.S., your comment about a state having only one action could use a
> little more explanation.
>
> I'll try but I really recommend you all get Lahman's book. The state
> action is performed upon entry to the state. Thus, there can be only
> one action and it must always be the same. If a different action is
> needed then, by definition, the object must enter a different state.
> The UML and various other state machine notations allow more
> expressive syntax but the expressive syntax tends to be a crutch.
> Sticking to the bare-bones FSA notation makes it more difficult to
> solve structural problems with dynamic solutions. If your state chart
> is getting complicated, don't switch to a more compact syntax; fix the
> structural problems that are causing the dynamic complexity.

Sounds fine. My only caveat is that the Mealy model (actions on
transitions) is mathematically equivalent. Thus one can have multiple,
different actions to enter the state, but since only one transition is
triggered, only one action with one set of rules and poliices is
actually executed. The only restriction is that all the actions on the
transitions entering a particular state must process the same alphabet
(i.e., have the same event data packet definition). Thus the choice of
Moore vs. Mealy is purely methodological with Moore being a better fit
to OOA/D for other reasons.

UML and some methodologies allow exit actions, but I am not a fan of
that because it seems to me it violates the basic FSA definition that a
state is a condition where a unique set of rules and policies apply. If
you separate entry and exit actions, you now have two sets of rules and
policies that apply at different times.

I also agree that KISS rules. State machine complexity is a red flag
that the problem space abstraction was screwed up.

Peter Mueller

unread,
May 7, 2012, 1:11:36 PM5/7/12
to umlf...@googlegroups.com, umlf...@googlegroups.com
Hi,

think about generating code from UML state machines. Generating state machines is very well understood and can save you really a lot of manual coding work. Good generators also perform model checks which helps to make sure your model is complete regarding principal issues e.g. init states defined, no transitions without events ...

Am 07.05.2012 um 17:10 schrieb "H. S. Lahman" <h.la...@verizon.net>:

> Responding to George...
>
>> H.S., your comment about a state having only one action could use a little more explanation.
>>
>> I'll try but I really recommend you all get Lahman's book. The state action is performed upon entry to the state. Thus, there can be only one action and it must always be the same. If a different action is needed then, by definition, the object must enter a different state. The UML and various other state machine notations allow more expressive syntax but the expressive syntax tends to be a crutch. Sticking to the bare-bones FSA notation makes it more difficult to solve structural problems with dynamic solutions. If your state chart is getting complicated, don't switch to a more compact syntax; fix the structural problems that are causing the dynamic complexity.
>
> Sounds fine. My only caveat is that the Mealy model (actions on transitions) is mathematically equivalent. Thus one can have multiple, different actions to enter the state, but since only one transition is triggered, only one action with one set of rules and poliices is actually executed. The only restriction is that all the actions on the transitions entering a particular state must process the same alphabet (i.e., have the same event data packet definition). Thus the choice of Moore vs. Mealy is purely methodological with Moore being a better fit to OOA/D for other reasons.
>
> UML and some methodologies allow exit actions, but I am not a fan of that because it seems to me it violates the basic FSA definition that a state is a condition where a unique set of rules and policies apply. If you separate entry and exit actions, you now have two sets of rules and policies that apply at different times.

Wit best regards,
Peter



Dan George

unread,
May 7, 2012, 3:23:12 PM5/7/12
to umlf...@googlegroups.com
I agree. It would be easy to screw up the alphabet restriction using Mealy notation. The convenience of Mealy notation comes when the action to be performed depends on the "from" state. Many transitions can be drawn, each with it's own action attached, to a single destination state. Despite being equivalent, Mealy looks simpler in this case because it has fewer states. Don't be fooled because the "simpler" notation only makes it easier to screw up. Even going with Moore notation, you may be tempted to "simplify" by adding flags to the alphabet. The state action can check the flag to see what it is supposed to do. For some reason, this is more attractive than having a bunch of "extra" states. Again, look to instead to fix complicated state machines with enlightened structure (enlightened because the complicated state model should be giving you some hints).

Sorry, writing these things out helps me improve my understanding. Just figured I might as well share.

Dan

H. S. Lahman

unread,
May 8, 2012, 10:58:56 AM5/8/12
to umlf...@googlegroups.com
Responding to Mueller...

>
> think about generating code from UML state machines. Generating state machines is very well understood and can save you really a lot of manual coding work. Good generators also perform model checks which helps to make sure your model is complete regarding principal issues e.g. init states defined, no transitions without events ...

You are bringing coals to Newcastle. B-) I have been advocating
translation techniques (full code generation from a 4GL model) for over
two decades.

The caution I have, though, is the one I expressed to the OP. Too often
the piecemeal code generators that just do UML Statecharts use the GoF
State pattern, which is not a good way to do it.

Peter Mueller

unread,
May 8, 2012, 1:55:57 PM5/8/12
to umlf...@googlegroups.com
Hi,

Am 08.05.2012 um 16:58 schrieb "H. S. Lahman" <h.la...@verizon.net>:

> Responding to Mueller...
>
>>
>> think about generating code from UML state machines. Generating state machines is very well understood and can save you really a lot of manual coding work. Good generators also perform model checks which helps to make sure your model is complete regarding principal issues e.g. init states defined, no transitions without events ...
>
> You are bringing coals to Newcastle. B-) I have been advocating translation techniques (full code generation from a 4GL model) for over two decades.
>
> The caution I have, though, is the one I expressed to the OP. Too often the piecemeal code generators that just do UML Statecharts use the GoF State pattern, which is not a good way to do it.


I agree. For a generator the GoF pattern does not make sense from point of view either. I offer a generator especially for the embedded domain (www.sinelabore.com). And the generated code is simply based on switch/case and if/else if constructs - clear, easy to understand and compact.

The main benefit of generation is if changes or new requirements comes into the arena. Then hand written state code is really hard to maintain.

Peter

dgl...@glaserresearch.net

unread,
May 8, 2012, 12:31:33 PM5/8/12
to umlforum
Responding to H. S. Lahman -

Do you have any pointers to "good" mappings of state machines to code?

-David
=================================

H. S. Lahman

unread,
May 9, 2012, 12:05:44 PM5/9/12
to umlf...@googlegroups.com
Responding to dglaser...

>
> Do you have any pointers to "good" mappings of state machines to code?

Not really. The commercial translation transformation engines are pricey
because the venders have to recover a large investment (optimization is
a much tougher problem than a 3GL compiler). So they tend to treat that
stuff as proprietary.

However, I can describe one way to translate object state machines that
is fairly common. In the target implementation OOPL, each class has a
static State Transition Table that is a jump table indexed by {current
state, event ID} to determine what method will be invoked. (This works
pretty much the same way as the object's virtual method jump table works
under he hood.) There is also a static processEvent() method that takes
the event and a pointer to the object in hand as arguments. (The pointer
serves the same function as the compiler's implied 'this' pointer.) The
event queue manager invokes this static method when it pops an event.
Events are stored in the event queue as objects consisting of {event ID,
target object, target class ID, data packet}. The event queue uses the
class ID as a lookup to invoke the correct class' processEvent method.

The processEvent() method looks up the private currentState attribute
from the object reference and uses that with the event ID to do the STT
lookup to invoke the method. The object method is invoked with the
reference as an argument so that it can access the object state data
(attributes), pretty much the way OOPLs use implied 'this' pointers
under the hood. The first thing the object method does is update the
object's currentState attribute.

The event queue provide serialization of asynchronous processing by
popping only one event at a time. Another event cannot be popped until
the current state action completes because the call to processEvent() is
synchronous. Generally one has a single event queue per subsystem. But
one can provide a poor man's threading by using multiple event queue
managers to process different events. (Caveat: only in simple
situations. This is not foolproof.)

This is just a basic outline. There are lots of ways to optimize the
details and get around the language type system, depending on the
vagaries of the particular target language. For example, some languages
will allow you to bypass the processEvent() method so the event queue
manager does the invocation directly from the STT. You will note,
though, that the class and the object are defined quite naturally. In
fact, if one decided to produce a pure synchronous implementation by
removing the event queue queue, static STT, and processEvent() while
substituting direct method calls for event generation, one would not be
able to tell a state machine was being used.

[Converting the Statechart to a synchronous implementation, of course,
implies an act of faith because without the STT lookup there is no
longer a "can't happen" error check. And if the collaborations are not
truly synchronous, lots of strange things may happen. B-) That's why
asynchronous communications are more difficult to get working properly,
but once they are working, they tend to be more robust. It is also why
asynchronous communications are the most general way to manage object
collaborations.]

Dan George

unread,
May 9, 2012, 10:30:27 PM5/9/12
to umlf...@googlegroups.com
You can also check out Miro Samek's Practical Statecharts in C/C++. The book shows how to code many of the constructs supported by the UML with Miro's Quantum Framework. The mappings are straight forward especially if you limit the UML syntax to the Executable UML profile.

Dan
Reply all
Reply to author
Forward
0 new messages