Transition and reaction difference in FSM?

Davy wrote:

Hi all,

I found there are transition and reaction in FSM/HSM. I only know there
is state transition in FSM. What's reaction mean? And what's there
difference?

BTW, I am studing Statecharts (or called Hierarchical State Machine,
i.e. HSM). Is it useful in software/hardware design?

Any suggestions are welcome!


Best regards,
Davy
Generally state machines are divided into Mealy and Moore:

http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/Seq/fsm.html

Once you get beyond that, there are hierarchical state machines, timed
automata, etc. It depends on what you are trying to do with the model
(generate code, verify properties, both, neither, etc.).

The goal of most modeling frameworks is to allow enough modeling
richness that humans can understand the model, and allow enough
independence that models can be reused in other systems. That first one
is a losing battle--humans aren't good at understanding all possible
behaviors of stateful systems.

Generally, all state machines are equivalent regardless of the modeling
framework. There are algorithms to convert from various formalisms to
various other formalisms.

As far as the construction of software, the absolute minimization of
state is usually more important than the modeling framework. There is
much to say in that department, but you didn't ask.

State machine design is very important in embedded systems.
------------------------------------------------------------
David T. Ashley (dta@e3ft.com)
http://www.e3ft.com (Consulting Home Page)
http://www.dtashley.com (Personal Home Page)
http://gpl.e3ft.com (GPL Publications and Projects)
 
In article <%1clh.20$SQ1.14@trnddc03>, H. S. Lahman says...
Responding to Adsett...
One is required to "follow" those transitions in the software external
to the FSM in the sense that events must be generated and delivered in
an order consistent with the FSM structure (i.e., events arrive when the
FSM is in the proper current state). But I think that is a separate
problem for asynchronous communications (e.g., handshaking protocols)
and serializing mechanisms like event queues.


I can see you could build a FSM this way and it might even be required
in some cases but it does seem rather cumbersome. It seems to require
two copies of the FSM one to perform the transitions and one to decide
which transitions are valid. Surely part of the essence of a state
machine is you deal with events as they occur rather than reording them
to suit?

Sorry, but you have lost me here. I only see one FSM. Defining the
states and transitions in an FSM is driven by the problem space. The
result of that process of problem space abstraction is the <single> FSM
that executes as the problem is solved.
It appears to be implied by your requirement above that the software
external to the FSM must know what state the FSM is in in order ro
generate the proper events.

Events are just messages that announce some change in the state of the
overall problem solution.
And here you lose me again.

1 - Events cause transitions
2 - Transistions change states
3 - Changes in state are annouced via events
4 - See step 1

Even in a trivial case like:

[Opened]
| ^
| |
V |
[Closed]

there are problem space rules that say that it makes no sense to execute
the [Opened] action twice in succession.


Which would be why the during action is such a state would be null
presumably. Or the opened state would have a transition to an idle
state occupied once the open was successful.

I'm not sure what you mean by "during action".


OK, the FSMs I build use the following basic contructs.

Transitions with
conditions (such as load > LOAD_MAX)
actions (such as motor_off(); )
States with
on-entry actions executed on entry to the state
on-exit actions executed on exit from the state
during actions executed while in the state.

IOW, a "during action" is something like a continuously running polling
loop? FWIW, I think that notion violates the basic rules of finite
state automata in a major way.
No, it's a periodically executed action. It performs actions, I don't
think I've ever done one that polled input.

In an FSA, the action processes the input alphabet and it assumed to be
instantaneous. [The Mealy FSM model was developed because some purists
had a problem with the fact that actions took finite time to execute in
practice and that meant there was an ambiguous period when the FSM was
not in either the prior state or the new state for the transition.
Putting actions on transitions allowed the FSM to remain in the prior
state until the transition was completed and then instantaneously
transition to the target state.]
A quick aside on timing. The transistions may in some abstract sense be
instantaneous but in most of the state machines I write the transitions
from state to state are 'clocked' in the sense they can take place only
at certain regular intervals. This clocking is vital to the correct
behaviour.

I would also argue that for the "during action" to do anything useful it
must somehow change the state of the overall solution (e.g., generate an
event or set an attribute if the hardware provides an interrupt). IOW,
the action must do something that will observable externally or after
its completion. Otherwise there would be no way to determine that it
actually did anything. So if the "during action" does do something
visible outside the state, then it is modifying the the state. This is
particularly worrisome because that change could take place _at any
time_ while the object is supposedly in the state.
Let me provide a simplified example. Consider a motor control with the
following inputs:
- Forward (on or off)
- Reverse (on or off)
- Throttle (0 to Max)

From these and domain knowledge (which I leave out for brevity) we end
up with a simple state chart to describe the drive control signal that
will be sent to the drive control process.

State 1 - Stop Waiting for a proper direction signal. The throttle
must be zero and both direction switches off before exiting this state.
Only one transition allowed which is to neutral when the previous
conditions are satisfied.
On Entry Action -> DriveRequest = 0;

State 2 - Neutral Waiting for direction. Multiple possible
transistions
On Entry Action -> DriveRequest = 0;
Tr A - ((Throttle > 0) || (Forward && Reverse)) Back to Stop.
State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && Reverse) To Reverse. State 4


State 3 - Forward. Multiple possible transistions
During Action -> DriveRequest = Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (!Forward && Reverse) To Reverse. State 4
Tr C - (!Forward && !Reverse) To Neutral. State 2

State 4 - Reverse. Multiple possible transistions
During Action -> DriveRequest = -Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && !Reverse) To Neutral. State 2

Now I suppose you could take each possible throttle setting as a
separate state but... I would argue that the during action doesn't
actually cause any change of state, it is essential to proper operation
though.

I have a similar problem with exit actions. If they do something
useful, then the state of the application is different than it was when
the entry action completed and it is different than the result of any
actions associated with the target state. IOW, one really has an
intermediate FSM state that isn't shown in the FSM. If purists could
get upset enough about Moore to provide Mealy, they would surely be
uptight about this. B-)
Let me pose another simple example. Some states need to be reflected to
the operator in an explicit fashion so for a state that needs this I
might have the following:
On Entry Action -> SetIndicatorLamp();
On Exit Action -> ClearIndicatorLamp();

Also, rather than setting a lamp this might be something essential to
operation like turning on lubrication or cooling.

Now this could be simulated with multiple states and transitions but
this introduces timing issues for clocked machines (there are
workarounds) and expands the number of states for IMHO no apparent good
reason.

As it happens I can accept exit actions in an OO context because object
FSMs have some of their input alphabet provided by state variables
rather than event data packets. So the notion of processing one subset
of the input on entry and another subset on exit makes some degree of
sense -- given that the OO context also has to deal with actions taking
finite time because Moore is a better fit. IOW, to accept exit actions
one is accepting the same furry boundary between states that one accepts
with the Moore FSM model.

So I can rationalize exit actions, but "during actions" are far too
open-ended in their abuse of the notion of 'state'. As a practical
matter one has mechanisms to deal with ambiguities around actions taking
finite time to execute (e.g., an event queue waiting until the current
event is fully consumed before popping the next event) on the boundary
between states. But there are no equivalent mechanisms for managing a
"during action" that is executing in the background even when the object
is quiescent. Essentially one is introducing concurrent processing
without benefit of management.
Ahh, maybe I see. A during action doesn't imply a background execution
process. It implies an action that takes place on each cycle of the
state machine. See my note about clocked execution earlier.

Robert

--
Posted via a free Usenet account from http://www.teranews.com
 
Responding to Adsett...

One is required to "follow" those transitions in the software external
to the FSM in the sense that events must be generated and delivered in
an order consistent with the FSM structure (i.e., events arrive when the
FSM is in the proper current state). But I think that is a separate
problem for asynchronous communications (e.g., handshaking protocols)
and serializing mechanisms like event queues.


I can see you could build a FSM this way and it might even be required
in some cases but it does seem rather cumbersome. It seems to require
two copies of the FSM one to perform the transitions and one to decide
which transitions are valid. Surely part of the essence of a state
machine is you deal with events as they occur rather than reording them
to suit?

Sorry, but you have lost me here. I only see one FSM. Defining the
states and transitions in an FSM is driven by the problem space. The
result of that process of problem space abstraction is the <single> FSM
that executes as the problem is solved.


It appears to be implied by your requirement above that the software
external to the FSM must know what state the FSM is in in order ro
generate the proper events.
The software external to the FSM does not even have to know the FSM
exists. The event is simply an announcement of something that happened
externally. It is the job of the developer to determine who cares
(i.e., which FSM) about what happened and address the event properly
(e.g., at the level of a UML Interaction Diagram).

Events are just messages that announce some change in the state of the
overall problem solution.


And here you lose me again.

1 - Events cause transitions
2 - Transistions change states
3 - Changes in state are annouced via events
4 - See step 1
Your step (3) is essentially what I am talking about. When the state
changes in a particular FSM, that manifests a change in the overall
state of the solution. So the event generated in (3) is an announcement
of that change.

However, the link between (3) and (1) is achieved by addressing that
announcement to an FSM that cares about the change. That mapping is
driven by the overall solution to the problem (e.g., algorithmic
sequencing or data integrity issues for state variables) rather than any
inherent expectation of what should happen next _in the action for (3)_.

Note the the underlying rules for FSAs stipulate that a state cannot
know what the prior state was or the next state will be. So the action
in (3) cannot anticipate what transition in (1) will be triggered (or
even what FSM that transition lives in).

Even in a trivial case like:

[Opened]
| ^
| |
V |
[Closed]

there are problem space rules that say that it makes no sense to execute
the [Opened] action twice in succession.


Which would be why the during action is such a state would be null
presumably. Or the opened state would have a transition to an idle
state occupied once the open was successful.

I'm not sure what you mean by "during action".


OK, the FSMs I build use the following basic contructs.

Transitions with
conditions (such as load > LOAD_MAX)
actions (such as motor_off(); )
States with
on-entry actions executed on entry to the state
on-exit actions executed on exit from the state
during actions executed while in the state.

IOW, a "during action" is something like a continuously running polling
loop? FWIW, I think that notion violates the basic rules of finite
state automata in a major way.


No, it's a periodically executed action. It performs actions, I don't
think I've ever done one that polled input.
OK, but I think my same arguments apply so long as those activities
occur /while/ the object in some state.

Typically that sort of periodic behavior is handled with timers. The
timer generates an event that triggers a transition in some FSM and the
action executes the periodic behavior. Thus each execution of the
periodic action is triggered by an individual event and there is a
transition of the FSM (albeit usually reflexive).

[Note that in OOA/D the timers, like event queues, are not even
explicitly modeled. They are assumed to be implemented in some
architectural subsystem.]

In an FSA, the action processes the input alphabet and it assumed to be
instantaneous. [The Mealy FSM model was developed because some purists
had a problem with the fact that actions took finite time to execute in
practice and that meant there was an ambiguous period when the FSM was
not in either the prior state or the new state for the transition.
Putting actions on transitions allowed the FSM to remain in the prior
state until the transition was completed and then instantaneously
transition to the target state.]


A quick aside on timing. The transistions may in some abstract sense be
instantaneous but in most of the state machines I write the transitions
from state to state are 'clocked' in the sense they can take place only
at certain regular intervals. This clocking is vital to the correct
behaviour.
That's fine, but I think it is a separate issue that one handles with
timers and explicit events/transitions in the FSM.

The Mealy/Moore issue is about the ambiguity of what state the FSM is in
while the action is executing. It doesn't make any difference because
we have other rules, such as an event queue only popping one event at a
time, that ensure the ambiguity is transparent in practice. IOW, the
infrastructure around the FSM ensures the software behaves exactly _as
if_ the action execution were instantaneous.

I would also argue that for the "during action" to do anything useful it
must somehow change the state of the overall solution (e.g., generate an
event or set an attribute if the hardware provides an interrupt). IOW,
the action must do something that will observable externally or after
its completion. Otherwise there would be no way to determine that it
actually did anything. So if the "during action" does do something
visible outside the state, then it is modifying the the state. This is
particularly worrisome because that change could take place _at any
time_ while the object is supposedly in the state.


Let me provide a simplified example. Consider a motor control with the
following inputs:
- Forward (on or off)
- Reverse (on or off)
- Throttle (0 to Max)

From these and domain knowledge (which I leave out for brevity) we end
up with a simple state chart to describe the drive control signal that
will be sent to the drive control process.

State 1 - Stop Waiting for a proper direction signal. The throttle
must be zero and both direction switches off before exiting this state.
Only one transition allowed which is to neutral when the previous
conditions are satisfied.
On Entry Action -> DriveRequest = 0;

State 2 - Neutral Waiting for direction. Multiple possible
transistions
On Entry Action -> DriveRequest = 0;
Tr A - ((Throttle > 0) || (Forward && Reverse)) Back to Stop.
State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && Reverse) To Reverse. State 4


State 3 - Forward. Multiple possible transistions
During Action -> DriveRequest = Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (!Forward && Reverse) To Reverse. State 4
Tr C - (!Forward && !Reverse) To Neutral. State 2

State 4 - Reverse. Multiple possible transistions
During Action -> DriveRequest = -Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && !Reverse) To Neutral. State 2

Now I suppose you could take each possible throttle setting as a
separate state but... I would argue that the during action doesn't
actually cause any change of state, it is essential to proper operation
though.
I am reluctant to pull a Topmind and start critiquing the FSM for
reasons unrelated to the point in hand (using "during actions").
Instead, let just say I think I would do it differently... B-)

Apropos of my point above, I think I would want an FSM where one of the
events signaled a change in throttle because changing the throttle
setting seems like it it quite important to running a motor. I am also
suspicious that the notions of 'forward' and 'reverse' can be completely
captured in object attributes rather than FSM states. That's because
the direction and throttle settings are really just register writes of
values. IOW, I think When one is allowed to change direction and
throttle is more important to the solution than the specific values. So
I would probably abstract an object like:

[Motor]
+ direction
+ currentThrottleSetting

with an FSM something like (assuming the motor must stop before changing
direction when running):

E3:ThrottleChange
+-------+
| |
| V
[ThrottleChanged] <---------------+
| |
| E1:Stop |
V |
[Stopped] | E3:ThrottleChange
| |
| E2:DirectionChange |
V |
[DirectionChanged]----------------+

State: Stopped. Same as yours

State: DirectionChanged. Changes Motor.direction and talks to hardware.

State: ThrottleChanged. Changes Motor.currentThrottleSetting and talks
to hardware. If Motor.currentThrottleSetting is 0, generate E1:Stop.

Event: E1:Stop ()
Event: E2:DirectionChange (direction)
Event: E3:ThrottleChange (setting)

[A purist would get bent over E1 being a self-directed event but this
happens to be one of the classic examples where avoiding it would
require additional states and transitions that would (IMO) substantially
reduce comprehensibility. So it is a practical trade-off I am willing
to make.]

Note that if the hardware allows the direction to be reversed without
stopping, then all one adds are a couple of more transitions for E2 and
E3 events. Also note that in addition to eliminating the "during
action", this model also eliminates the complexity of conditional
transitions.

Bottom line: I think one can construct relatively simple FSMs without
"during actions".

I have a similar problem with exit actions. If they do something
useful, then the state of the application is different than it was when
the entry action completed and it is different than the result of any
actions associated with the target state. IOW, one really has an
intermediate FSM state that isn't shown in the FSM. If purists could
get upset enough about Moore to provide Mealy, they would surely be
uptight about this. B-)


Let me pose another simple example. Some states need to be reflected to
the operator in an explicit fashion so for a state that needs this I
might have the following:
On Entry Action -> SetIndicatorLamp();
On Exit Action -> ClearIndicatorLamp();

Also, rather than setting a lamp this might be something essential to
operation like turning on lubrication or cooling.

Now this could be simulated with multiple states and transitions but
this introduces timing issues for clocked machines (there are
workarounds) and expands the number of states for IMHO no apparent good
reason.
Not necessarily. I think a lot depends upon where one allocates the
intelligence in the overall solution. One can imagine

|
| E1:toggle
V
[IndicatorChanged] <--------+
| |
| |
+-------------------+
E1:toggle

for the first example. Here the ON/OFF state is maintained as a state
variable and one just writes to the hardware based on <changing> the
current value. The real smarts that understands the broader context and
determines WHEN the indicator needs to change lives elsewhere.

For the second example, lubrication vs. cooling, I submit that in an OO
context those are distinct behavior responsibilities at the object level
that should be self-contained and encapsulated. That is, they each
represent a unique set of rules and policies in the hardware control
realm. When mapping to object FSMs, one usually thinks of a state as a
condition where a unique suite of rules and policies prevails. So I
submit that in an OO context one /wants/ to associate lubrication and
cooling with different states to decouple them explicitly. If one does
that, then managing the object FSM interactions becomes a whole lot easier.

However, I think this is somewhat academic since I already agreed that
exit actions have their uses in practice and the theoretical issues
really aren't a problem in practice. So let's agree to partially agree
on exit actions.

As it happens I can accept exit actions in an OO context because object
FSMs have some of their input alphabet provided by state variables
rather than event data packets. So the notion of processing one subset
of the input on entry and another subset on exit makes some degree of
sense -- given that the OO context also has to deal with actions taking
finite time because Moore is a better fit. IOW, to accept exit actions
one is accepting the same furry boundary between states that one accepts
with the Moore FSM model.

So I can rationalize exit actions, but "during actions" are far too
open-ended in their abuse of the notion of 'state'. As a practical
matter one has mechanisms to deal with ambiguities around actions taking
finite time to execute (e.g., an event queue waiting until the current
event is fully consumed before popping the next event) on the boundary
between states. But there are no equivalent mechanisms for managing a
"during action" that is executing in the background even when the object
is quiescent. Essentially one is introducing concurrent processing
without benefit of management.


Ahh, maybe I see. A during action doesn't imply a background execution
process. It implies an action that takes place on each cycle of the
state machine. See my note about clocked execution earlier.
Then I'm now confused. B-) What do you mean by "each cycle of the
state machine"? In particular, what is actually going on in your FSM
where you have:

During Action -> DriveRequest = Throttle

How does the During Action get invoked if there is no event triggering a
transition? (I assumed it was some asynchronous mechanism like a
callback method being invoked, but that invocation would be independent
of the FSM cycle.) What exactly is a Drive Request? (I assumed it was
some attribute.) What does During Action actually do? (I assumed
something more than just setting the DriveRequest attribute, since that
would just be an orthogonal knowledge setter.) How do you ensure that
this During Action is not invoked when the FSM is in some other state?


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
 
In article <L9ylh.6082$c94.5368@trndny09>, H. S. Lahman says...
Responding to Adsett...

One is required to "follow" those transitions in the software external
to the FSM in the sense that events must be generated and delivered in
an order consistent with the FSM structure (i.e., events arrive when the
FSM is in the proper current state). But I think that is a separate
problem for asynchronous communications (e.g., handshaking protocols)
and serializing mechanisms like event queues.


I can see you could build a FSM this way and it might even be required
in some cases but it does seem rather cumbersome. It seems to require
two copies of the FSM one to perform the transitions and one to decide
which transitions are valid. Surely part of the essence of a state
machine is you deal with events as they occur rather than reording them
to suit?

Sorry, but you have lost me here. I only see one FSM. Defining the
states and transitions in an FSM is driven by the problem space. The
result of that process of problem space abstraction is the <single> FSM
that executes as the problem is solved.


It appears to be implied by your requirement above that the software
external to the FSM must know what state the FSM is in in order ro
generate the proper events.

The software external to the FSM does not even have to know the FSM
exists.
Beg pardon? 'One is required to "follow" those transitions in the
software external to the FSM'

The event is simply an announcement of something that happened
externally.
OK, but that appears to be inconsistent with 'events arrive when the
FSM is in the proper current state'. Maybe you meant something
different but that reads to me as the events the FSM recieves depends on
the state it is in, and the 'required to follow' reads as the external
SW is reponsible for ensuring that the proper filtering and sorting is
done to ensure the proper arrival of the events.

It is the job of the developer to determine who cares
(i.e., which FSM) about what happened and address the event properly
(e.g., at the level of a UML Interaction Diagram).
Um, yes, of course. But what has that to do with the original statement?

Methinks we have a language gap of some sort.


Events are just messages that announce some change in the state of the
overall problem solution.


And here you lose me again.

1 - Events cause transitions
2 - Transistions change states
3 - Changes in state are annouced via events
4 - See step 1

Your step (3) is essentially what I am talking about. When the state
changes in a particular FSM, that manifests a change in the overall
state of the solution. So the event generated in (3) is an announcement
of that change.

However, the link between (3) and (1) is achieved by addressing that
announcement to an FSM that cares about the change.
So there's more than one FSM involved? That changes things. If you are
generating events in one FSM to be consumed in other separate FSMs then
in that case all you are saying is the output of an FSM is useful.

That mapping is
driven by the overall solution to the problem (e.g., algorithmic
sequencing or data integrity issues for state variables) rather than any
inherent expectation of what should happen next _in the action for (3)_.
I'm confused again. What mapping are you talking about?

Note the the underlying rules for FSAs stipulate that a state cannot
know what the prior state was or the next state will be. So the action
in (3) cannot anticipate what transition in (1) will be triggered (or
even what FSM that transition lives in).
Say what?

OK, the FSMs I build use the following basic contructs.

Transitions with
conditions (such as load > LOAD_MAX)
actions (such as motor_off(); )
States with
on-entry actions executed on entry to the state
on-exit actions executed on exit from the state
during actions executed while in the state.

IOW, a "during action" is something like a continuously running polling
loop? FWIW, I think that notion violates the basic rules of finite
state automata in a major way.


No, it's a periodically executed action. It performs actions, I don't
think I've ever done one that polled input.

OK, but I think my same arguments apply so long as those activities
occur /while/ the object in some state.

Typically that sort of periodic behavior is handled with timers. The
timer generates an event that triggers a transition in some FSM and the
action executes the periodic behavior. Thus each execution of the
periodic action is triggered by an individual event and there is a
transition of the FSM (albeit usually reflexive).
Yes it could be simulated by a reflexive transistion. If it makes you
any happier think of it as a reflexive transition that skips any on-
entry or on-exit actions. I see no way that it is any different. It
just leaves the diagram a little cleaner.

A quick aside on timing. The transistions may in some abstract sense be
instantaneous but in most of the state machines I write the transitions
from state to state are 'clocked' in the sense they can take place only
at certain regular intervals. This clocking is vital to the correct
behaviour.

That's fine, but I think it is a separate issue that one handles with
timers and explicit events/transitions in the FSM.
Not at all, that would clutter up the FSM with timers on every
transition.


Let me provide a simplified example. Consider a motor control with the
following inputs:
- Forward (on or off)
- Reverse (on or off)
- Throttle (0 to Max)

From these and domain knowledge (which I leave out for brevity) we end
up with a simple state chart to describe the drive control signal that
will be sent to the drive control process.

State 1 - Stop Waiting for a proper direction signal. The throttle
must be zero and both direction switches off before exiting this state.
Only one transition allowed which is to neutral when the previous
conditions are satisfied.
On Entry Action -> DriveRequest = 0;

State 2 - Neutral Waiting for direction. Multiple possible
transistions
On Entry Action -> DriveRequest = 0;
Tr A - ((Throttle > 0) || (Forward && Reverse)) Back to Stop.
State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && Reverse) To Reverse. State 4


State 3 - Forward. Multiple possible transistions
During Action -> DriveRequest = Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (!Forward && Reverse) To Reverse. State 4
Tr C - (!Forward && !Reverse) To Neutral. State 2

State 4 - Reverse. Multiple possible transistions
During Action -> DriveRequest = -Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && !Reverse) To Neutral. State 2

Now I suppose you could take each possible throttle setting as a
separate state but... I would argue that the during action doesn't
actually cause any change of state, it is essential to proper operation
though.

I am reluctant to pull a Topmind and start critiquing the FSM for
reasons unrelated to the point in hand (using "during actions").
Instead, let just say I think I would do it differently... B-)

Apropos of my point above, I think I would want an FSM where one of the
events signaled a change in throttle because changing the throttle
setting seems like it it quite important to running a motor.
One of the issues with that is the throttle changes continuously. This
sort of state machine usually executes one cycle per control loop. A
throttle changed event would fire every cycle. It's a lot simpler to
just view it as a continuous input.

I am also
suspicious that the notions of 'forward' and 'reverse' can be completely
captured in object attributes rather than FSM states. That's because
the direction and throttle settings are really just register writes of
values.
Ultimately everything can be completely captured with attributes and
calculated as needed. A state machine just captures some of that
information in the state. The key is whether the state machine captures
the intent in a simpler and/or more robust fashion. Of course many of
those constructs will just be state machines developed in a more opaque
fashion.

The incoming signals can indicate forward, reverse, neutral or be
invalid. The throttle can independantly be anywhere in its range. In a
complete example it could also be out of range but I did want a simple
example :) I also don't deal here with finite allowable tme to switch
directions, deadman switches and anti-tiedown logic :)

As a result of these the output could be forward, reverse, neutral or
stop.

Forward and reverse are distinct, it's tempting to treat them
identically but there is usually an assymetry in speed or some other
associated behaviour. You could treat forward and reverse the same but
IME it's easier to disentangle them here rather than later. And once
you treat them separately they really are distinct states. There is
duplication only in the degenerate case.

There is not a lot of distinction visible in this example between
neutral and stop but they are different. Neutral is a normal operating
state but stop is a fault state from which the operator is required to
return to a specified starting setup before continuing. I'll try to
make the distinction clearer in the modified example.

IOW, I think When one is allowed to change direction and
throttle is more important to the solution than the specific values. So
I would probably abstract an object like:

[Motor]
+ direction
+ currentThrottleSetting

with an FSM something like (assuming the motor must stop before changing
direction when running):
Hmm, I don't think I was clear enough here. Actually I wasn't clear at
all, my apologies. This FSM describes the evaluation of the control
signals not the motor control. The actual motor control is done
elsewhere.


E3:ThrottleChange
+-------+
| |
| V
[ThrottleChanged] <---------------+
| |
| E1:Stop |
V |
[Stopped] | E3:ThrottleChange
| |
| E2:DirectionChange |
V |
[DirectionChanged]----------------+

State: Stopped. Same as yours
Hmm, I'm not sure it does. It looks closer to my neutral state. but I
think I simplified my neutral state too much.

State: DirectionChanged. Changes Motor.direction and talks to hardware.

State: ThrottleChanged. Changes Motor.currentThrottleSetting and talks
to hardware. If Motor.currentThrottleSetting is 0, generate E1:Stop.

Event: E1:Stop ()
Event: E2:DirectionChange (direction)
Event: E3:ThrottleChange (setting)

[A purist would get bent over E1 being a self-directed event but this
happens to be one of the classic examples where avoiding it would
require additional states and transitions that would (IMO) substantially
reduce comprehensibility. So it is a practical trade-off I am willing
to make.]
Purists didn't much like Dirac deltas when they were introduced either.
That didn't prevent everybody else from using them to advantage though.
Not that I'm claiming any of this approaches the usefulness of a delta
function though. :)

Note that if the hardware allows the direction to be reversed without
stopping, then all one adds are a couple of more transitions for E2 and
E3 events. Also note that in addition to eliminating the "during
action", this model also eliminates the complexity of conditional
transitions.
?? The transitions are still conditional, they still rely on the events
occuring. I see no difference between your conditions and the
conditions I used other than a layer of syntactic sugar. You are also
missing start sequencing and the direction interlock both of which are
critical.

Bottom line: I think one can construct relatively simple FSMs without
"during actions".
This reworking partly works as long as the directions are symmetrical
but it also moves a fair piece of the logic outside the state machine
making it less clear what is happening. You have removed the during
action but at the expense of implementing it elsewhere. It's now more
difficult to tell if the result is correct.

It's certainly possible to implement FSMs without during actions. It's
also possible to implement procedural code without for, while or do
loops. That doesn't mean the constructs are not useful though.

Let me pose another simple example. Some states need to be reflected to
the operator in an explicit fashion so for a state that needs this I
might have the following:
On Entry Action -> SetIndicatorLamp();
On Exit Action -> ClearIndicatorLamp();

Also, rather than setting a lamp this might be something essential to
operation like turning on lubrication or cooling.

Now this could be simulated with multiple states and transitions but
this introduces timing issues for clocked machines (there are
workarounds) and expands the number of states for IMHO no apparent good
reason.

Not necessarily. I think a lot depends upon where one allocates the
intelligence in the overall solution. One can imagine

|
| E1:toggle
V
[IndicatorChanged] <--------+
| |
| |
+-------------------+
E1:toggle

for the first example. Here the ON/OFF state is maintained as a state
variable and one just writes to the hardware based on <changing> the
current value. The real smarts that understands the broader context and
determines WHEN the indicator needs to change lives elsewhere.
Doesn't that add another state machine where previously there was one?
It also changes an absolute set/clear to a toggle. Something I'd be
reluctant to do without a lot bigger benefit than getting rid of exit
actions.

So I can rationalize exit actions, but "during actions" are far too
open-ended in their abuse of the notion of 'state'. As a practical
matter one has mechanisms to deal with ambiguities around actions taking
finite time to execute (e.g., an event queue waiting until the current
event is fully consumed before popping the next event) on the boundary
between states. But there are no equivalent mechanisms for managing a
"during action" that is executing in the background even when the object
is quiescent. Essentially one is introducing concurrent processing
without benefit of management.


Ahh, maybe I see. A during action doesn't imply a background execution
process. It implies an action that takes place on each cycle of the
state machine. See my note about clocked execution earlier.

Then I'm now confused. B-) What do you mean by "each cycle of the
state machine"? In particular, what is actually going on in your FSM
where you have:

During Action -> DriveRequest = Throttle

How does the During Action get invoked if there is no event triggering a
transition? (I assumed it was some asynchronous mechanism like a
callback method being invoked, but that invocation would be independent
of the FSM cycle.) What exactly is a Drive Request? (I assumed it was
some attribute.)
Caareful about your assumptions ;). It's just meant to be an assignment
statement. The value is then fed on to the actual motor control which
could be another state machine or a D/A setting to another controller
entirely or ....

What does During Action actually do? (I assumed
something more than just setting the DriveRequest attribute, since that
would just be an orthogonal knowledge setter.) How do you ensure that
this During Action is not invoked when the FSM is in some other state?
I don't understand the question, how could it get invoked if you were in
another state?

Let me revise the example a bit to include asymmetry in the directions
as would be typical. I'll also walk through a couple of iterations so
you can get an idea of how the during actions work.

State 1 - Stop Waiting for a proper direction signal. The throttle
must be zero and both direction switches off before exiting this state.
Only one transition allowed which is to neutral when the previous
conditions are satisfied.
On Entry Action -> DriveRequest = 0;

State 2 - Neutral Waiting for direction. Multiple possible
transistions
On Entry Action -> DriveRequest = 0;
Tr A - (Forward && Reverse) Back to Stop. State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && Reverse) To Reverse. State 4


State 3 - Forward. Multiple possible transistions
During Action -> DriveRequest = Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (!Forward && Reverse) To Reverse. State 4
Tr C - (!Forward && !Reverse) To Neutral. State 2

State 4 - Reverse. Multiple possible transistions
On Entry Action -> SetReverseAlarm();
During Action -> DriveRequest = -Throttle/2;
On Exit Action -> ClearReverseAlarm();
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && !Reverse) To Neutral. State 2


Note 1: The reverse alarm setup is more naive than would actually be
used (by a fair amount) but it keeps the example simpler.

Note 2: I've modified the neutral state to more properly reflect the
difference between it and the stop state. In a less naive example the
neutral state would be a little more complex.

The statechart is implemented as a function, each call check for valid
transitions and performs them before returning. The values checked and
returned will be in the argument list, I'll leave the details out.

Now to walk through. The state machine is already initialized to be in
state 1

Time=t0
Conditions - Forward and Reverse are false, throttle is 0,
DriveRequest is 0 (from entering state 1 some time previously)
call to statechart
state changes to state 2
DriveRequest is set to 0
returns

Time=t1
Conditions - Forward is false, Reverse is true, throttle is 0
call to statechart
state changes to state 4
DriveRequest is set to 0
call to SetReverseAlarm()
returns

Time=t2
Conditions - Forward is false, Reverse is true, throttle is 500
call to statechart
DriveRequest is set to -250
returns

Time=t3
Conditions - Forward is false, Reverse is true, throttle is 490
call to statechart
DriveRequest is set to -245
returns

Time=t4
Conditions - Forward is true, Reverse is false, throttle is 310
call to statechart
call to ClearReverseAlarm()
state changes to state 3
DriveRequest is set to 310
returns

etc...

And of course this could be implemented in just about any language C,
ASM, ST or even as a method in an OO language.

Robert

--
Posted via a free Usenet account from http://www.teranews.com
 
Responding to Adsett...

It wasn't until I got to the end that I realized most of this thread is
a tempest in a teapot and we have been talking past on another. You
might want to skip to the end an read my closing comments first.

In addition, I am suspicious that you are not developing in an OO
environment despite posting to comp.object (where I live).

One is required to "follow" those transitions in the software external
to the FSM in the sense that events must be generated and delivered in
an order consistent with the FSM structure (i.e., events arrive when the
FSM is in the proper current state). But I think that is a separate
problem for asynchronous communications (e.g., handshaking protocols)
and serializing mechanisms like event queues.


I can see you could build a FSM this way and it might even be required
in some cases but it does seem rather cumbersome. It seems to require
two copies of the FSM one to perform the transitions and one to decide
which transitions are valid. Surely part of the essence of a state
machine is you deal with events as they occur rather than reording them
to suit?

Sorry, but you have lost me here. I only see one FSM. Defining the
states and transitions in an FSM is driven by the problem space. The
result of that process of problem space abstraction is the <single> FSM
that executes as the problem is solved.


It appears to be implied by your requirement above that the software
external to the FSM must know what state the FSM is in in order ro
generate the proper events.

The software external to the FSM does not even have to know the FSM
exists.


Beg pardon? 'One is required to "follow" those transitions in the
software external to the FSM'
As I explained in the description of applying DbC, the developer can
decide where <announcement> events go /after/ designing the object FSMs.
So one does not need to know anything about that when designing an
individual object FSM. Hence the individual object FSM is independent
of context and does not need to know the receiving FSM even exists.

What I was referring to with the "follow" remark was that object FSMs
are not designed in a vacuum. Objects are abstracted from the problem
space with one eye on the problem to be solved. That is, the object
abstraction is tailored to the needs of the overall solution by
determining what knowledge and behavior responsibilities must be
abstracted to solve the problem in hand.

The OO paradigm provides methodological guidance for how to do problem
space abstraction (e.g., defining logically indivisible behavior
responsibilities) that ensures that once the object is properly
abstracted, an asynchronous behavior communication model will Just Work
if one uses object state machines.

For example, handshaking is an ancient notion in R-T/E. So the
traditional way of designing interacting FSMs was to define handshaking
protocols for synchronization and then build the FSMs around those
protocols. But what those protocols were really doing is providing a
systematic approach to ensuring a functional granularity that was
detailed enough so that one could connect the flow of control dots with
messages. The OO paradigm essentially already provides that when doing
problem space abstraction.

You lubrication vs. cooling example demonstrates that. The OO paradigm
dictates that they are distinct responsibilities that need to be
encapsulated separately and decoupled. That leads to associating each
one with its own state so they are triggered by different messages. In
turn, that guarantees a granularity such that one can synchronize the
flow of control by connecting the dots with individual events using DbC
(with a little serialization help from the event queue).

The event is simply an announcement of something that happened
externally.


OK, but that appears to be inconsistent with 'events arrive when the
FSM is in the proper current state'. Maybe you meant something
different but that reads to me as the events the FSM recieves depends on
the state it is in, and the 'required to follow' reads as the external
SW is reponsible for ensuring that the proper filtering and sorting is
done to ensure the proper arrival of the events.
I submit that is the only way a rigorous DbC approach to flow of control
can work. The event cannot depend on what is going to happen; it can
only depend on what it is announcing that the sender did.

As for the synchronization with current state, that is what DbC provides
in the OO paradigm (or handshaking protocols in non-OO paradigms).

It is the job of the developer to determine who cares
(i.e., which FSM) about what happened and address the event properly
(e.g., at the level of a UML Interaction Diagram).


Um, yes, of course. But what has that to do with the original statement?
I was responding to your assertion:

"It appears to be implied by your requirement above that the software
external to the FSM must know what state the FSM is in in order to
generate the proper events."

I was trying to explain why that inference is not valid.

Events are just messages that announce some change in the state of the
overall problem solution.


And here you lose me again.

1 - Events cause transitions
2 - Transistions change states
3 - Changes in state are annouced via events
4 - See step 1

Your step (3) is essentially what I am talking about. When the state
changes in a particular FSM, that manifests a change in the overall
state of the solution. So the event generated in (3) is an announcement
of that change.

However, the link between (3) and (1) is achieved by addressing that
announcement to an FSM that cares about the change.


So there's more than one FSM involved? That changes things. If you are
generating events in one FSM to be consumed in other separate FSMs then
in that case all you are saying is the output of an FSM is useful.
Purists would argue that self-directed events are illegal; that all the
events triggering transitions must be generated outside the FSM. In
addition, the events must be synchronized in some manner with the
inherent sequencing rules of the FSM transitions. So there are almost
always at least two FSMs. In an OO application if FSMs are used at all,
then every object having behavior responsibilities will have an FSM.
(In translation methodologies the use of FSMs is mandatory for all
applications.)

That mapping is
driven by the overall solution to the problem (e.g., algorithmic
sequencing or data integrity issues for state variables) rather than any
inherent expectation of what should happen next _in the action for (3)_.


I'm confused again. What mapping are you talking about?
The mapping between the event generated in (3) and what transition it
triggers in (1).

Note the the underlying rules for FSAs stipulate that a state cannot
know what the prior state was or the next state will be. So the action
in (3) cannot anticipate what transition in (1) will be triggered (or
even what FSM that transition lives in).


Say what?
In an FSA the state action can only process the input alphabet. IOW,
the only thing the state action can understand about context is the
provided alphabet.

OK, the FSMs I build use the following basic contructs.

Transitions with
conditions (such as load > LOAD_MAX)
actions (such as motor_off(); )
States with
on-entry actions executed on entry to the state
on-exit actions executed on exit from the state
during actions executed while in the state.

IOW, a "during action" is something like a continuously running polling
loop? FWIW, I think that notion violates the basic rules of finite
state automata in a major way.


No, it's a periodically executed action. It performs actions, I don't
think I've ever done one that polled input.

OK, but I think my same arguments apply so long as those activities
occur /while/ the object in some state.

Typically that sort of periodic behavior is handled with timers. The
timer generates an event that triggers a transition in some FSM and the
action executes the periodic behavior. Thus each execution of the
periodic action is triggered by an individual event and there is a
transition of the FSM (albeit usually reflexive).


Yes it could be simulated by a reflexive transistion. If it makes you
any happier think of it as a reflexive transition that skips any on-
entry or on-exit actions. I see no way that it is any different. It
just leaves the diagram a little cleaner.
You can only do that with a Mealy model because the action depends on
the transition rather than the state. As I indicated, I think the Moore
model is better suited to the OO paradigm. Since Moore and Mealy models
are convertible, though, one could always convert the Mealy to a Moore
(albeit possibly at the cost of an extra state). So one can get to the
same <Moore> place without "during actions".

My argument here is that if the "during action" is triggered by
something other than a transition, then one is asking for trouble
because one cannot rely on the usual infrastructures like event queues
to ensure data and referential integrity "for free".

A quick aside on timing. The transistions may in some abstract sense be
instantaneous but in most of the state machines I write the transitions
from state to state are 'clocked' in the sense they can take place only
at certain regular intervals. This clocking is vital to the correct
behaviour.

That's fine, but I think it is a separate issue that one handles with
timers and explicit events/transitions in the FSM.


Not at all, that would clutter up the FSM with timers on every
transition.
The timers aren't in the FSM. They are architectural mechanisms that
are orthogonal to the FSM. In an OOA/D model they wouldn't even appear
explicitly; they would be manifested in external events that trigger the
transitions in the FSM.

In addition, one only uses the timer to provide the sort of periodic
triggering that you described. Then the event condition raised is based
on some duration of clock time elapsing. That is completely independent
of the dynamic sequencing within the solution. So one needs an
orthogonal mechanism like timers to deal with it.

Let me provide a simplified example. Consider a motor control with the
following inputs:
- Forward (on or off)
- Reverse (on or off)
- Throttle (0 to Max)

From these and domain knowledge (which I leave out for brevity) we end
up with a simple state chart to describe the drive control signal that
will be sent to the drive control process.

State 1 - Stop Waiting for a proper direction signal. The throttle
must be zero and both direction switches off before exiting this state.
Only one transition allowed which is to neutral when the previous
conditions are satisfied.
On Entry Action -> DriveRequest = 0;

State 2 - Neutral Waiting for direction. Multiple possible
transistions
On Entry Action -> DriveRequest = 0;
Tr A - ((Throttle > 0) || (Forward && Reverse)) Back to Stop.
State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && Reverse) To Reverse. State 4


State 3 - Forward. Multiple possible transistions
During Action -> DriveRequest = Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (!Forward && Reverse) To Reverse. State 4
Tr C - (!Forward && !Reverse) To Neutral. State 2

State 4 - Reverse. Multiple possible transistions
During Action -> DriveRequest = -Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && !Reverse) To Neutral. State 2

Now I suppose you could take each possible throttle setting as a
separate state but... I would argue that the during action doesn't
actually cause any change of state, it is essential to proper operation
though.

I am reluctant to pull a Topmind and start critiquing the FSM for
reasons unrelated to the point in hand (using "during actions").
Instead, let just say I think I would do it differently... B-)

Apropos of my point above, I think I would want an FSM where one of the
events signaled a change in throttle because changing the throttle
setting seems like it it quite important to running a motor.


One of the issues with that is the throttle changes continuously. This
sort of state machine usually executes one cycle per control loop. A
throttle changed event would fire every cycle. It's a lot simpler to
just view it as a continuous input.
You mentioned "throttle settings". To me that implies a <smallish>
finite number of discrete values. And in your example below you employ
discrete values.

I am also unsure what you mean by 'cycle' and 'control loop' here.

In any event, I don't see how you can view it as continuous changes
unless there is a direct hardware link between the physical throttle
control and the motor -- in which case the software is irrelevant.
Software is digital, which means that it is inherently discrete. In the
end a software controller for hardware can only read and write hardware
registers at discrete intervals. So one can only emulate analog
(continuous) hardware processes with some variant of time slicing and
that infrastructure needs to be built into the software explicitly.

[I've done hardware controllers for analog devices and it is a real
pain. The hardware has to provide the D-to-A conversion. Even then,
trying to provide the required granularity is tough to do. So much so
that I would be very tempted to put the throttle's continuous emulation
(i.e., the infrastructure needed to slice it) in its own object with its
own FSM and leave stuff like direction changing to somebody else who is
looking at the Big Picture.]

I am also
suspicious that the notions of 'forward' and 'reverse' can be completely
captured in object attributes rather than FSM states. That's because
the direction and throttle settings are really just register writes of
values.


Ultimately everything can be completely captured with attributes and
calculated as needed. A state machine just captures some of that
information in the state. The key is whether the state machine captures
the intent in a simpler and/or more robust fashion. Of course many of
those constructs will just be state machines developed in a more opaque
fashion.

The incoming signals can indicate forward, reverse, neutral or be
invalid. The throttle can independantly be anywhere in its range. In a
complete example it could also be out of range but I did want a simple
example :) I also don't deal here with finite allowable tme to switch
directions, deadman switches and anti-tiedown logic :)

As a result of these the output could be forward, reverse, neutral or
stop.
My issue is: why can't the incoming signal be changeDirection rather
than an explicit Forward/Reverse couplet? The only problem space rule
that seems likely to be relevant is that the motor needs to be in
Neutral when the direction is changed. The direction itself is just a
data element that the hardware interprets. The fact that it is stored
in a hardware register rather than a memory location doesn't prevent it
from being viewed as an object knowledge attribute that some other
object sets.

Forward and reverse are distinct, it's tempting to treat them
identically but there is usually an assymetry in speed or some other
associated behaviour. You could treat forward and reverse the same but
IME it's easier to disentangle them here rather than later. And once
you treat them separately they really are distinct states. There is
duplication only in the degenerate case.

There is not a lot of distinction visible in this example between
neutral and stop but they are different. Neutral is a normal operating
state but stop is a fault state from which the operator is required to
return to a specified starting setup before continuing. I'll try to
make the distinction clearer in the modified example.
OK.

IOW, I think When one is allowed to change direction and
throttle is more important to the solution than the specific values. So
I would probably abstract an object like:

[Motor]
+ direction
+ currentThrottleSetting

with an FSM something like (assuming the motor must stop before changing
direction when running):


Hmm, I don't think I was clear enough here. Actually I wasn't clear at
all, my apologies. This FSM describes the evaluation of the control
signals not the motor control. The actual motor control is done
elsewhere.
I agree, that is a big difference. B-) Alas, without more words around
what "evaluation" means in your problem context, I can't speculate on
how I would eliminate the "during action".

Note that if the hardware allows the direction to be reversed without
stopping, then all one adds are a couple of more transitions for E2 and
E3 events. Also note that in addition to eliminating the "during
action", this model also eliminates the complexity of conditional
transitions.


?? The transitions are still conditional, they still rely on the events
occuring. I see no difference between your conditions and the
conditions I used other than a layer of syntactic sugar. You are also
missing start sequencing and the direction interlock both of which are
critical.
There are no conditional events for my Motor abstraction. The events
are raised in other objects that understand when and why, say, a
direction needs to be changed. It is up to the developer to connect the
flow of control dots via DbC to provide the necessary synchronization
unconditionally.

For example, Let's say object A has an action, doIt, that issues the
E3:changeDirection event. The precondition for transitioning to the
A::doIt state is that Motor is in the Stopped state (neutral now). That
condition is announced by generating, say, the E52:inNeutral event when
the Motor enters that state. The developer then matches the
Motor::neutral postcondition to the A::doIt precondition and addresses
that event to A's FSM. That handshaking synchronizes the FSMs.

Bottom line: I think one can construct relatively simple FSMs without
"during actions".


This reworking partly works as long as the directions are symmetrical
but it also moves a fair piece of the logic outside the state machine
making it less clear what is happening. You have removed the during
action but at the expense of implementing it elsewhere. It's now more
difficult to tell if the result is correct.
I don't buy that argument because one is managing complexity through
separating concerns and decomposing functionality into more manageable
chunks. Providing better maintainability, of which comprehensibility
and verifying correctness are important aspects, is the raison d'etre of
the OO paradigm. Providing simple, highly cohesive, and
context-independent objects is crucial to achieving that. In addition,
DbC provides a quite formal and rigorous technique for ensuring correctness.

However, I think the real issue with "during actions" is that they
invite problems because they violate the underlying FSA rules. If the
"during action" does anything at all useful to the solution, it is
actually changing the state of the solution, as manifested by the FSM
state. So long as that can happen at any time while the FSM is in a
given state, one has opened a Pandora's Box of data and referential
integrity problems that are far worse that any delegation of
responsibilities among multiple objects. IMO, a "during action"
completely trashes the primary value of using FSMs in the first place:
providing a disciplined framework for execution.

Let me pose another simple example. Some states need to be reflected to
the operator in an explicit fashion so for a state that needs this I
might have the following:
On Entry Action -> SetIndicatorLamp();
On Exit Action -> ClearIndicatorLamp();

Also, rather than setting a lamp this might be something essential to
operation like turning on lubrication or cooling.

Now this could be simulated with multiple states and transitions but
this introduces timing issues for clocked machines (there are
workarounds) and expands the number of states for IMHO no apparent good
reason.

Not necessarily. I think a lot depends upon where one allocates the
intelligence in the overall solution. One can imagine

|
| E1:toggle
V
[IndicatorChanged] <--------+
| |
| |
+-------------------+
E1:toggle

for the first example. Here the ON/OFF state is maintained as a state
variable and one just writes to the hardware based on <changing> the
current value. The real smarts that understands the broader context and
determines WHEN the indicator needs to change lives elsewhere.


Doesn't that add another state machine where previously there was one?
It also changes an absolute set/clear to a toggle. Something I'd be
reluctant to do without a lot bigger benefit than getting rid of exit
actions.
I don't think so. I am replacing your state having entry and exit
actions with state that has only one entry action. The difference is
that instead of two different events in sequence to turn ON and then
turn OFF (one transitioning to the state and the other transitioning out
of it), one sends two toggle events that both transition to it.

So I can rationalize exit actions, but "during actions" are far too
open-ended in their abuse of the notion of 'state'. As a practical
matter one has mechanisms to deal with ambiguities around actions taking
finite time to execute (e.g., an event queue waiting until the current
event is fully consumed before popping the next event) on the boundary
between states. But there are no equivalent mechanisms for managing a
"during action" that is executing in the background even when the object
is quiescent. Essentially one is introducing concurrent processing
without benefit of management.


Ahh, maybe I see. A during action doesn't imply a background execution
process. It implies an action that takes place on each cycle of the
state machine. See my note about clocked execution earlier.

Then I'm now confused. B-) What do you mean by "each cycle of the
state machine"? In particular, what is actually going on in your FSM
where you have:

During Action -> DriveRequest = Throttle

How does the During Action get invoked if there is no event triggering a
transition? (I assumed it was some asynchronous mechanism like a
callback method being invoked, but that invocation would be independent
of the FSM cycle.) What exactly is a Drive Request? (I assumed it was
some attribute.)


Caareful about your assumptions ;). It's just meant to be an assignment
statement. The value is then fed on to the actual motor control which
could be another state machine or a D/A setting to another controller
entirely or ....
[ed. Here is where we really diverge. It becomes clear later that what
you meant by "during action" and what I inferred were two very different
things.]

But then it is nothing but a knowledge setter and has no business being
in an FSM. One uses object FSMs to describe behavior responsibilities.
Knowledge and behavior responsibilities are completely different
worlds because knowledge accessors are always synchronous in OOA/D while
FSMs are inherently asynchronous.

What does During Action actually do? (I assumed
something more than just setting the DriveRequest attribute, since that
would just be an orthogonal knowledge setter.) How do you ensure that
this During Action is not invoked when the FSM is in some other state?


I don't understand the question, how could it get invoked if you were in
another state?
By your description the "during action" is an action that is invoked
while the containing FSM is in a particular state. My understanding of
"during" is that the action gets invoked at any arbitrary time within
the time interval that the FSM is in that state.

Since it is not triggered by an FSM event, someone external to the FSM
must invoke it. That invocation mechanism is orthogonal to the FSM
invocation mechanism (triggering transitions). Therefore it would seem
possible that whoever that is could be invoking the action
asynchronously without regard to or knowledge of the current FSM state.
So my question is: how do you make sure that external entity only
invokes the method when the FSM is in a particular state?

Let me revise the example a bit to include asymmetry in the directions
as would be typical. I'll also walk through a couple of iterations so
you can get an idea of how the during actions work.

State 1 - Stop Waiting for a proper direction signal. The throttle
must be zero and both direction switches off before exiting this state.
Only one transition allowed which is to neutral when the previous
conditions are satisfied.
On Entry Action -> DriveRequest = 0;

State 2 - Neutral Waiting for direction. Multiple possible
transistions
On Entry Action -> DriveRequest = 0;
Tr A - (Forward && Reverse) Back to Stop. State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && Reverse) To Reverse. State 4


State 3 - Forward. Multiple possible transistions
During Action -> DriveRequest = Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (!Forward && Reverse) To Reverse. State 4
Tr C - (!Forward && !Reverse) To Neutral. State 2

State 4 - Reverse. Multiple possible transistions
On Entry Action -> SetReverseAlarm();
During Action -> DriveRequest = -Throttle/2;
On Exit Action -> ClearReverseAlarm();
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && !Reverse) To Neutral. State 2


Note 1: The reverse alarm setup is more naive than would actually be
used (by a fair amount) but it keeps the example simpler.

Note 2: I've modified the neutral state to more properly reflect the
difference between it and the stop state. In a less naive example the
neutral state would be a little more complex.

The statechart is implemented as a function, each call check for valid
transitions and performs them before returning. The values checked and
returned will be in the argument list, I'll leave the details out.

Now to walk through. The state machine is already initialized to be in
state 1

Time=t0
Conditions - Forward and Reverse are false, throttle is 0,
DriveRequest is 0 (from entering state 1 some time previously)
call to statechart
state changes to state 2
DriveRequest is set to 0
returns

Time=t1
Conditions - Forward is false, Reverse is true, throttle is 0
call to statechart
state changes to state 4
DriveRequest is set to 0
call to SetReverseAlarm()
returns

Time=t2
Conditions - Forward is false, Reverse is true, throttle is 500
call to statechart
DriveRequest is set to -250
returns

Time=t3
Conditions - Forward is false, Reverse is true, throttle is 490
call to statechart
DriveRequest is set to -245
returns

Time=t4
Conditions - Forward is true, Reverse is false, throttle is 310
call to statechart
call to ClearReverseAlarm()
state changes to state 3
DriveRequest is set to 310
returns

etc...

And of course this could be implemented in just about any language C,
ASM, ST or even as a method in an OO language.
OK. AFAICT, this a function takes arguments of {isForward, isReverse,
throttle} and uses them to set the value of DriveRequest and,
optionally, invoke two other functions for ReverseAlarm. To do that it
needs to understand the history of prior invocations, which is
summarized in a value for current state.

If so, then I don't see any "during action". There is only one "event"
and it is always the call to the function. The only thing that changes
are the values in the data packet. That "event" is dispatched to the
appropriate "call to statechart" method for each state based on the
value of current state and the data packet values. Then the value of
DriveRequest is always set on entry to the current state using the rules
and policies that prevail for that state. IOW, this seems to be an
ordinary Moore FSM with only entry actions (i.e., the individual "call
to statechart" method for each state).

All you are doing is including the STT dispatch mechanism that would
usually be in external supporting infrastructure (i.e., the event queue
or static class-level lookup) in the function call. The state actions
are the individual methods for "call to statechart". The body of those
methods, including setting DriveRequest, is executed all at once on
entry to the state.

BTW, I would argue that this is not an FSM at all. It is simply a
single synchronous service that uses a state variable to record history.
That is, "current state" really represents a state variable for
context that is computed from the prior context variable value and the
current input values. The calls to ReverseAlarm are just ordinary
conditional message generation based on the state variable values. IOW,

new context value = F(last context value, isForward, isReverse, throttle).

is a single deterministic computation. Because it depends upon the
input alphabet values rather than just {event ID, current state}, it
isn't a true FSM.

I could easily implement your function as a single procedure without
distinct "action" methods. [That's not a criticism, BTW. Using
FSM-like reasoning and structure provides good discipline. I am just
arguing that (a) it isn't a true FSM because current state is computed
from the input alphabet and (b) it would be an ordinary Moore FSM even
if it were.]


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
 
In article <TrUlh.1145$kB3.113@trnddc08>, H. S. Lahman says...
Responding to Adsett...

It wasn't until I got to the end that I realized most of this thread is
a tempest in a teapot and we have been talking past on another. You
might want to skip to the end an read my closing comments first.
Sigh I had a detailed reponse but it just got lost. Maybe we're better
off :)

In addition, I am suspicious that you are not developing in an OO
environment despite posting to comp.object (where I live).
If you check you'll see it's cross posted to c.a.e. Why the original
poster crosposted this way I don't know but I've been using this
discussion to try to learn from your perspective. I figure the sig I'm
adding may be appropriate though.


You lubrication vs. cooling example demonstrates that.
Um, it's not vs, They were separate examples.

The incoming signals can indicate forward, reverse, neutral or be
invalid. The throttle can independantly be anywhere in its range. In a
complete example it could also be out of range but I did want a simple
example :) I also don't deal here with finite allowable tme to switch
directions, deadman switches and anti-tiedown logic :)

As a result of these the output could be forward, reverse, neutral or
stop.

My issue is: why can't the incoming signal be changeDirection rather
than an explicit Forward/Reverse couplet?
I suppose they could be but you would then still have to figure out
which direction it had changed to. I suppose you could generate
different events for each possibility but I think we've lost the
advantage at that point.

The only problem space rule
that seems likely to be relevant is that the motor needs to be in
Neutral when the direction is changed. The direction itself is just a
data element that the hardware interprets. The fact that it is stored
in a hardware register rather than a memory location doesn't prevent it
from being viewed as an object knowledge attribute that some other
object sets.
Agreed, in fact in some cases it's not a direct input.

Let me revise the example a bit to include asymmetry in the directions
as would be typical. I'll also walk through a couple of iterations so
you can get an idea of how the during actions work.

State 1 - Stop Waiting for a proper direction signal. The throttle
must be zero and both direction switches off before exiting this state.
Only one transition allowed which is to neutral when the previous
conditions are satisfied.
On Entry Action -> DriveRequest = 0;

State 2 - Neutral Waiting for direction. Multiple possible
transistions
On Entry Action -> DriveRequest = 0;
Tr A - (Forward && Reverse) Back to Stop. State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && Reverse) To Reverse. State 4


State 3 - Forward. Multiple possible transistions
During Action -> DriveRequest = Throttle;
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (!Forward && Reverse) To Reverse. State 4
Tr C - (!Forward && !Reverse) To Neutral. State 2

State 4 - Reverse. Multiple possible transistions
On Entry Action -> SetReverseAlarm();
During Action -> DriveRequest = -Throttle/2;
On Exit Action -> ClearReverseAlarm();
Tr A - (Forward && Reverse) To Stop. State 1
Tr B - (Forward && !Reverse) To Forward. State 3
Tr C - (!Forward && !Reverse) To Neutral. State 2


Note 1: The reverse alarm setup is more naive than would actually be
used (by a fair amount) but it keeps the example simpler.

Note 2: I've modified the neutral state to more properly reflect the
difference between it and the stop state. In a less naive example the
neutral state would be a little more complex.

The statechart is implemented as a function, each call check for valid
transitions and performs them before returning. The values checked and
returned will be in the argument list, I'll leave the details out.

Now to walk through. The state machine is already initialized to be in
state 1

Time=t0
Conditions - Forward and Reverse are false, throttle is 0,
DriveRequest is 0 (from entering state 1 some time previously)
call to statechart
state changes to state 2
DriveRequest is set to 0
returns

Time=t1
Conditions - Forward is false, Reverse is true, throttle is 0
call to statechart
state changes to state 4
DriveRequest is set to 0
call to SetReverseAlarm()
returns

Time=t2
Conditions - Forward is false, Reverse is true, throttle is 500
call to statechart
DriveRequest is set to -250
returns

Time=t3
Conditions - Forward is false, Reverse is true, throttle is 490
call to statechart
DriveRequest is set to -245
returns

Time=t4
Conditions - Forward is true, Reverse is false, throttle is 310
call to statechart
call to ClearReverseAlarm()
state changes to state 3
DriveRequest is set to 310
returns

etc...

And of course this could be implemented in just about any language C,
ASM, ST or even as a method in an OO language.

OK. AFAICT, this a function takes arguments of {isForward, isReverse,
throttle} and uses them to set the value of DriveRequest and,
optionally, invoke two other functions for ReverseAlarm. To do that it
needs to understand the history of prior invocations, which is
summarized in a value for current state.

If so, then I don't see any "during action". There is only one "event"
and it is always the call to the function. The only thing that changes
are the values in the data packet. That "event" is dispatched to the
appropriate "call to statechart" method for each state based on the
value of current state and the data packet values. Then the value of
DriveRequest is always set on entry to the current state using the rules
and policies that prevail for that state. IOW, this seems to be an
ordinary Moore FSM with only entry actions (i.e., the individual "call
to statechart" method for each state).
OK, seems an odd way to view it to me but I can see the equivalency.

All you are doing is including the STT dispatch mechanism that would
usually be in external supporting infrastructure (i.e., the event queue
or static class-level lookup) in the function call. The state actions
are the individual methods for "call to statechart". The body of those
methods, including setting DriveRequest, is executed all at once on
entry to the state.

BTW, I would argue that this is not an FSM at all. It is simply a
single synchronous service that uses a state variable to record history.
That is, "current state" really represents a state variable for
context that is computed from the prior context variable value and the
current input values. The calls to ReverseAlarm are just ordinary
conditional message generation based on the state variable values. IOW,

new context value = F(last context value, isForward, isReverse, throttle).

is a single deterministic computation. Because it depends upon the
input alphabet values rather than just {event ID, current state}, it
isn't a true FSM.
OK, although I suspect the denizens of c.a.e would recognize both as
state machines. I could be wrong on that though the participants cover
quite a broad spectrum.

I could easily implement your function as a single procedure without
distinct "action" methods. [That's not a criticism, BTW. Using
FSM-like reasoning and structure provides good discipline. I am just
arguing that (a) it isn't a true FSM because current state is computed
from the input alphabet and (b) it would be an ordinary Moore FSM even
if it were.]
I've done it that way myself. I switched to an explicit state appraoch
for the reasons you suggested. Also to make it easier to explain
andverify the logic with people who are not familiar with progrmming
languages. A visual statechart is a little more obvious, unfortuanately
it's only a little.

I have enjoyed this BTW, hopefully it's not been too much of an
annoyance to you or anyone else.


Robert
--
From the Divided by a Common Language File (Edited to protect the
guilty)
ME - "I'd like to get Price and delivery for connector Part # XXXXX"
Dist./Rep - "$X.XX Lead time 37 days"
ME - "Anything we can do about lead time? 37 days seems a bit high."
Dist./Rep - "that is the lead time given because our stock is live....
we currently have stock."

--
Posted via a free Usenet account from http://www.teranews.com
 
In article <oQxmh.21185$c94.3340@trndny09>, H. S. Lahman says...
Responding to Adsett...

You lubrication vs. cooling example demonstrates that.


Um, it's not vs, They were separate examples.

?? You combined them for one state condition. I was using 'versus' to
argue against that precisely because of the apples/oranges thing.
No, at least that was not the intent. I was presenting them as examples
of behaviours that could be tightly coupled to a machines operating
state.

The incoming signals can indicate forward, reverse, neutral or be
invalid. The throttle can independantly be anywhere in its range. In a
complete example it could also be out of range but I did want a simple
example :) I also don't deal here with finite allowable tme to switch
directions, deadman switches and anti-tiedown logic :)

As a result of these the output could be forward, reverse, neutral or
stop.

My issue is: why can't the incoming signal be changeDirection rather
than an explicit Forward/Reverse couplet?


I suppose they could be but you would then still have to figure out
which direction it had changed to. I suppose you could generate
different events for each possibility but I think we've lost the
advantage at that point.

If one captures current direction in a state variable rather than in an
FSM state, then all one has is a toggle that is triggered by a single
event with no data packet. So I don't see a need for "different events".
Remember the incoming direction signal has four possible states. A
simple toggle won't work since from any specific diection indication you
could get any of the remaining three. So either you provide different
events for all possibilities or you pass in the new direction signal
information.

Thus in your example one could change the function arguments to
{directionIsToggled, throttleSetting}.
You need more information.

OK. AFAICT, this a function takes arguments of {isForward, isReverse,
throttle} and uses them to set the value of DriveRequest and,
optionally, invoke two other functions for ReverseAlarm. To do that it
needs to understand the history of prior invocations, which is
summarized in a value for current state.

If so, then I don't see any "during action". There is only one "event"
and it is always the call to the function. The only thing that changes
are the values in the data packet. That "event" is dispatched to the
appropriate "call to statechart" method for each state based on the
value of current state and the data packet values. Then the value of
DriveRequest is always set on entry to the current state using the rules
and policies that prevail for that state. IOW, this seems to be an
ordinary Moore FSM with only entry actions (i.e., the individual "call
to statechart" method for each state).


OK, seems an odd way to view it to me but I can see the equivalency.

Hmmm. I thought I was just mapping what you provided, so let me expand
on my analysis of the example...
I'm not disagreeing it just seems an odd viewpoint.

By your description (i.e., the statechart is implemented as a single
function) the function call is the event message to the FSM from the
external world. Since there is only one function call and it always has
the same data packet, there is only one event that triggers all
transitions. That's unusual for practical FSMs but not illegal; one
only /needs/ different events if there are multiple unconditional
transitions out of a state. (In your example multiple exiting
transitions is handled by conditional events.)

In your example, you identified a "call to statechart" whose body did
different things depending on what the state was. I assumed those were
the methods for individual state or transition actions since all the
business rules seemed to be contained in them. Those methods mapped
uniquely to states since you associated each one with a state number.
In addition, there were no other methods doing anything (other than the
transition dispatch in the function itself).

Those methods seem to be the only FSM actions in the example AND they
were explicitly associated with a particular state AND they were called
after a transition had been selected but before the 'current state' was
set. So they had to be executed while entering the state. Consequently
the FSM has to be a simple Moore FSM.
OK. The separation into On-entry/during/on-exit (and transition actions
too) actions is still useful though. The code generator then picks up
the appropriate combination for each transistion. That would otherwise
have to be done by the designer. The computer is much better at
consistently doing that than I am.

Since DriveRequest is set in the body of those actions rather than in
some other method, I don't see any "during action". That is, Drive
Request can only be set if an FSM event is consumed (i.e., the
statechart function is called) AND it is only set after a <conditional
transition is selected to a specific state AND the action seems to be a
Moore action. So I don't see any other interpretation.

The only thing I see as unusual in the example is the way that way
transitions were selected. It is done within the statechart function
rather than in a spearate event queue or through a static class STT
lookup table.
STT?

IOW, you are combining the event queue and STT in the
single function that initially consumes the event.

In addition, the dispatch is based upon the value of 'current state' and
the values of the input alphabet (event data packet). In a true FSM the
input alphabet is irrelevant and the dispatch is based the value of
'current state' and the event ID. That is, conditional transitions are
an overlay to a pure FSM that explicitly employs state variables, which
don't exist for FSAs.
I suppose you could convert all the conditional checks by running them
externally and producing event ids for each one. Seems a lot of work
just get get a abstract ID though. The other disadvantage I see with
that is the actual condition is now several steps removed from the
transition it causes.

FWIW, with regard to conditional transitions, I am a purist and don't
regard them as true FSMs for two reasons. One is that they aren't
necessary, as my model for Motor demonstrated. In three decades of
mucking with FSMs I've never used one. (That is the main thing I meant
when I said I would do the FSM "differently".) IOW, I see value in
keeping the notation simple even if is occasionally causes the developer
some slight inconvenience.
So far I don't see the abstract IDs as any simpler than the conditional
check. Actually I don't see that they are not fundamentally identical
unless you have something running around changing values behind the
state machines back which would be bad design practice IMO.

Why is
if( a < DFG ) {
QueueEvent(queue, QW);
}
if( b == GHJZZ ) {
QueueEvent(queue, QE);
}
StateChart( queue, out);

superior to
StateChart( a, b, out);


However, when selecting the transition to a state depends on state
variable values, one is in another ballpark because accessing those
variables is outside the scope of the target state action. In effect
one needs to manage two different scopes for data integrity while
consuming an event and one of them is not conveniently bounded by the
call stack.
You've lost me completely. The data passed in is valid for the call.
Sounds like it's bounded by the call stack to me.

[Commercial code generators tend to ignore the problem if they support
conditional transitions in UML Statecharts. IOW, they assume the
developer will make sure the tested state variable is correct in all
circumstances where an event can be consumed. But that just puts the
optimization problem in the developer's lap and adds the resolution of
nonfunctional requirements to the developer's problems.]
If you are referring to the inputs then how is that any different from
any other function or method call? Indeed unless you are passing in the
values via reference how would the issue arise at all?

I have enjoyed this BTW, hopefully it's not been too much of an
annoyance to you or anyone else.

I'm retired now so I've got time on my hands. B-) In addition, after
many moons in the business I find that I have an oversupply of opinions
that I need to get rid of anyway, so I welcome the opportunity.
In that case, glad to take up your excess time :)

Robert

--
Posted via a free Usenet account from http://www.teranews.com
 
Davy escribió:
Hi all,

I found there are transition and reaction in FSM/HSM. I only know there
is state transition in FSM. What's reaction mean? And what's there
difference?
IIRC, reaction is the name given by Rhapsody's creators to internal
transitions. An internal transition is one that causes an action without
leaving a state.

BTW, I am studing Statecharts (or called Hierarchical State Machine,
i.e. HSM). Is it useful in software/hardware design?
Yes.
 
Responding to Adsett...

You lubrication vs. cooling example demonstrates that.


Um, it's not vs, They were separate examples.

?? You combined them for one state condition. I was using 'versus' to
argue against that precisely because of the apples/oranges thing.


No, at least that was not the intent. I was presenting them as examples
of behaviours that could be tightly coupled to a machines operating
state.
The operative word is "a" [machine's operating state]. B-) In the
context I was arguing that /because/ they were quite different things
they should not be associated with the same state as entry and exit actions.

In a software FSM a state represents a condition where a unique set of
rules and policies prevails. A corollary is that the rules and policies
in that set will be cohesive. I believe this is important because it
can affect subsequent maintenance. Suppose we originally have

|
| E1:prepare
V
[Prepared]
|
| E2:start
V
[Running]

where the [Prepared] state has an entry action to lubricate and an exit
action to start cooling.

Now consider what happens when requirements change such that cooling is
triggered by a temperature sensor. Now cooling is triggered after the
motor is running rather than before. So one might introduce a new state
and transition:

|
| E1:prepare
V
[Prepared]
|
| E2:start
V
[Running]
|
| E3:cool
V
[Cooled]

To do that surgery must be performed to the [Prepared] state implementation.

Now suppose we recognized cooling as a distinct suite of rules and
policies in the /original/ state machine:

|
| E1:prepare
V
[Prepared]
|
| E3:cool
V
[Cooled]
|
| E2:start
V
[Running]

To convert to the new state machine for the new requirements, all we
have to do is update the STT and, perhaps, change where the E3 event is
generated. IOW, we can implement the change at the message flow of
control level without touching the [Prepared] state implementation.

The incoming signals can indicate forward, reverse, neutral or be
invalid. The throttle can independantly be anywhere in its range. In a
complete example it could also be out of range but I did want a simple
example :) I also don't deal here with finite allowable tme to switch
directions, deadman switches and anti-tiedown logic :)

As a result of these the output could be forward, reverse, neutral or
stop.

My issue is: why can't the incoming signal be changeDirection rather
than an explicit Forward/Reverse couplet?


I suppose they could be but you would then still have to figure out
which direction it had changed to. I suppose you could generate
different events for each possibility but I think we've lost the
advantage at that point.

If one captures current direction in a state variable rather than in an
FSM state, then all one has is a toggle that is triggered by a single
event with no data packet. So I don't see a need for "different events".


Remember the incoming direction signal has four possible states. A
simple toggle won't work since from any specific diection indication you
could get any of the remaining three. So either you provide different
events for all possibilities or you pass in the new direction signal
information.
I didn't want to go here, but this was one of the things I was referring
to when I said I would do things differently; but it has nothing to do
with FSMs per se. In your example the Forward and Reverse data are
serving double duty. Certain combinations (both ON or both OFF) have
additional semantics unrelated to direction.

That is very similar to return values being "normal" data when positive
and error codes when negative. Such semantic double duty can lead to
problems during maintenance (e.g., when requirements change and make
some negative values "normal" data or when your criteria for stopping
changes). IOW, separation of concerns applies to data domains are well
as behaviors.

I also have a problem with using them to trigger a transition to the
[Stop] state, which you said was an error state. Since they are input
alphabet values (i.e., part of the event data packet), what is being
checked is that consistent data is being provided. If one is using DbC
for design, that should be a responsibility of whoever generates the
event. Thus it is a precondition of consuming the event that the data
in the data packet be consistent. IOW, when using DbC any assertions
made about the input data are checking the correctness of the software,
not the consistency of the data.

When the software becomes broken, that's a job for exception handling.
One might still need a [Stop] state for recovery, but getting there is a
job for the exception handler rather than FSM design. (Typically the
exception handler is going to have to do other things, like flushing the
event queue, that the FSM itself should not be concerned with.)
However, this is getting pretty far OT.

OK. AFAICT, this a function takes arguments of {isForward, isReverse,
throttle} and uses them to set the value of DriveRequest and,
optionally, invoke two other functions for ReverseAlarm. To do that it
needs to understand the history of prior invocations, which is
summarized in a value for current state.

If so, then I don't see any "during action". There is only one "event"
and it is always the call to the function. The only thing that changes
are the values in the data packet. That "event" is dispatched to the
appropriate "call to statechart" method for each state based on the
value of current state and the data packet values. Then the value of
DriveRequest is always set on entry to the current state using the rules
and policies that prevail for that state. IOW, this seems to be an
ordinary Moore FSM with only entry actions (i.e., the individual "call
to statechart" method for each state).


OK, seems an odd way to view it to me but I can see the equivalency.

Hmmm. I thought I was just mapping what you provided, so let me expand
on my analysis of the example...


I'm not disagreeing it just seems an odd viewpoint.
I guess it depends on where the observer is standing...

By your description (i.e., the statechart is implemented as a single
function) the function call is the event message to the FSM from the
external world. Since there is only one function call and it always has
the same data packet, there is only one event that triggers all
transitions. That's unusual for practical FSMs but not illegal; one
only /needs/ different events if there are multiple unconditional
transitions out of a state. (In your example multiple exiting
transitions is handled by conditional events.)

In your example, you identified a "call to statechart" whose body did
different things depending on what the state was. I assumed those were
the methods for individual state or transition actions since all the
business rules seemed to be contained in them. Those methods mapped
uniquely to states since you associated each one with a state number.
In addition, there were no other methods doing anything (other than the
transition dispatch in the function itself).

Those methods seem to be the only FSM actions in the example AND they
were explicitly associated with a particular state AND they were called
after a transition had been selected but before the 'current state' was
set. So they had to be executed while entering the state. Consequently
the FSM has to be a simple Moore FSM.


OK. The separation into On-entry/during/on-exit (and transition actions
too) actions is still useful though. The code generator then picks up
the appropriate combination for each transistion. That would otherwise
have to be done by the designer. The computer is much better at
consistently doing that than I am.
My point here is that in your example I don't see any separation at all.
That is, I don't see a "during action". All I see is a simple Moore
FSM. The value of DriveRequest is always set in that <entry> action as
a direct result of consuming the event that triggered going to the state.

Since DriveRequest is set in the body of those actions rather than in
some other method, I don't see any "during action". That is, Drive
Request can only be set if an FSM event is consumed (i.e., the
statechart function is called) AND it is only set after a <conditional
transition is selected to a specific state AND the action seems to be a
Moore action. So I don't see any other interpretation.

The only thing I see as unusual in the example is the way that way
transitions were selected. It is done within the statechart function
rather than in a spearate event queue or through a static class STT
lookup table.


STT?
State Transition Table. There are two forms. In one the table cells
are the event ID and the rows/columns are [current state, new state].
That is the one commonly seen in theoretical discussions. In the other
the cells are new state and the rows/columns are [current state, event
ID]. In practice the second form is used in software FSMs but the cells
are pointer-to-function for the specific state action. Then the event
queue can dispatch directly to the action when an event is popped.

No offense intended, but how often have you used FSMs? This is a very
basic acronym for FSMs and almost all FSMs are implemented using one for
efficiency. I was already suspicious that you don't use a lot because
you used the "statechart function" to implement the event with embedded
processing for the conditional event dispatch. I had never seen anyone
do that before. B-) BTW, the two most common ways for implementing
software FSMs are the GoF State pattern (where the STT is used to
dynamically instantiate the relationship between Context and State) and
utilizing a reusable event queue infrastructure.

[All commercial full code generators employ the event queue
infrastructure. Personally I regard the GoF State pattern for FSMs as a
misuse of the pattern, but let's not go there.]

IOW, you are combining the event queue and STT in the
single function that initially consumes the event.

In addition, the dispatch is based upon the value of 'current state' and
the values of the input alphabet (event data packet). In a true FSM the
input alphabet is irrelevant and the dispatch is based the value of
'current state' and the event ID. That is, conditional transitions are
an overlay to a pure FSM that explicitly employs state variables, which
don't exist for FSAs.


I suppose you could convert all the conditional checks by running them
externally and producing event ids for each one. Seems a lot of work
just get get a abstract ID though. The other disadvantage I see with
that is the actual condition is now several steps removed from the
transition it causes.
Not necessarily. Recall my model for Motor. It was actually somewhat
simpler than your model. Its actions could do everything you said were
done in your FSM actions and its transitions enforced the same
sequencing rules that yours did. It just did it with different
conditions (states), events, and state variables.

I think the condition is only one step removed. The DbC precondition
for executing any state action exactly matches the postcondition of some
other action (i.e., the one where the event is generated to announce
that its postcondition prevails).

Having the condition decoupled from the action is actually an advantage
for maintenance. (One can argue that the entire OO paradigm is designed
around the separation of message and method to eliminate the
hierarchical dependencies associated with procedural imperatives.) So
long as the state actions are cohesive and self-contained, one can
easily connect the flow of control dots via DbC using event generation.

FWIW, with regard to conditional transitions, I am a purist and don't
regard them as true FSMs for two reasons. One is that they aren't
necessary, as my model for Motor demonstrated. In three decades of
mucking with FSMs I've never used one. (That is the main thing I meant
when I said I would do the FSM "differently".) IOW, I see value in
keeping the notation simple even if is occasionally causes the developer
some slight inconvenience.


So far I don't see the abstract IDs as any simpler than the conditional
check. Actually I don't see that they are not fundamentally identical
unless you have something running around changing values behind the
state machines back which would be bad design practice IMO.

Why is
if( a < DFG ) {
QueueEvent(queue, QW);
}
if( b == GHJZZ ) {
QueueEvent(queue, QE);
}
StateChart( queue, out);

superior to
StateChart( a, b, out);
There are several reasons. From an aesthetic perspective the FSM
provides /invariant/ constraints on /relative/ sequencing. They should
be invariant relative to the external context. However, 'a' and 'b' are
external context variables. If one moves the conditional dispatch into
the FSM, one is making the FSM context-dependent and increases the
probability of maintenance problems.

There are two ways the FSM can utilize context variables. The FSM
actions can access them parametrically for a computation within a state
action. That usage is well constrained with respect to scope.

The other thing they can affect is the sequencing of actions within the
FSM. That is essentially what conditional events do; they use context
variables to change the structure of the FSM on the fly. To me that is
kind of like an assigned GOTO in FORTRAN; it opens all sorts of
opportunities for unexpected side affects. IOW when one changes the
data semantics of the state variables one not only needs to worry about
what one computes from the data but which formula one uses to do the
computation.

That is an issue of separation of concerns. The FSM structure is
inherently static. Modifying transitions dynamically adds another
dimension of complexity to the FSM structure and that is probably not a
good idea.

One way that is manifested is in the notion of OO announcement messages
(I'm Done) compared to procedural imperative messages (Do This). The
event being generated announces a change in condition /outside/ the FSM.
That is, the event itself is announcing something happening
externally. As it happens that depends upon 'a' and 'b'. But it
announces a compound condition that also includes whatever the caller
did. IOW, the condition being announced is {(a < DFG), caller completed
its part of the solution} OR {(b == GHJZZ), caller completed its part of
the solution}.

More importantly, it includes a context decision that the IF statements
themselves define. Those IF statements implement problem space rules
and policies to determine exactly What should be announced. The FSM
only responds to the announcement. If one moves the IF statements into
the FSM itself, one is moving that external context decision into the
FSM. That external context decision probably isn't any of the FSM's
business; it should just respond to the decision's /result/.

Finally, when managing complexity it is wise to isolate related rules
and policies via encapsulation. It is highly unlikely that the rules
and policies that determine what event to generate will be logically
related to the rules and policies that the FSM exists to resolve. So if
one moves those rules and policies into the FSM, one is trashing the
cohesion of the FSM.

The bottom line is that the software will be more maintainable if one
decouples message and method, separates concerns, and encapsulates rules
and policies in a cohesive fashion. Superficially both your examples do
the same thing. But devil is in the details and from the perspective of
maintainability there are potentially huge differences when one gets to
the details.

However, when selecting the transition to a state depends on state
variable values, one is in another ballpark because accessing those
variables is outside the scope of the target state action. In effect
one needs to manage two different scopes for data integrity while
consuming an event and one of them is not conveniently bounded by the
call stack.


You've lost me completely. The data passed in is valid for the call.
Sounds like it's bounded by the call stack to me.
Sorry, I was thinking about the more common situation where conditional
transitions are based upon the values of persistent state variables
rather than values in the event data packet.

[I am biased because in OO applications one rarely sees data in event
data packets. Data integrity is easier to manage if the method accesses
attribute data directly on an as-needed basis since there is potentially
an arbitrary delay between when an event is generated and when it is
consumed in the asynchronous execution model. So pretty much the only
time one sees data packets is for situations like sensor readings where
all the values need to be taken from the same time slice.]


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
 
In article <TCSmh.10$5g.7@trndny01>, H. S. Lahman says...
In a software FSM a state represents a condition where a unique set of
rules and policies prevails. A corollary is that the rules and policies
in that set will be cohesive. I believe this is important because it
can affect subsequent maintenance. Suppose we originally have

|
| E1:prepare
V
[Prepared]
|
| E2:start
V
[Running]

where the [Prepared] state has an entry action to lubricate and an exit
action to start cooling.

Now consider what happens when requirements change such that cooling is
triggered by a temperature sensor. Now cooling is triggered after the
motor is running rather than before. So one might introduce a new state
and transition:
I'd use a different state machine in that case. Since it would be truly
independant of the machine operating state. For the kind of state
dependance I'm referring to this kind of change would be rare. It would
require changing the machine, a much more daunting task than modifying
the state machine. Even if it is likely the simplicity of viewing the
behaviour is a single state machine is, in this case, an advantage.
Once the behaviour is no longer dependant on the state the
multiplicitive increase in states alone makes a separate state machine
attractive. More to the point it matches the problem domain.

Also it's not as if creating an additional state machine at that point
is difficult, it's a small addition to the work needed to add the new
temperature input. One thing to remember is we are not dealing with a
general purpose library here, these behaviours tend to be specific to
the application environment and if a behaviour is tightly coupled to a
state it's very likely to remain so.

The most recent occaision I've had reason for using that coupled on-
entry/on-exit construct was for flagging a fault state. On entry to the
fault state the flag would be set, on exit it would be cleared. You
could do the same thing by performing the action on the transitions
instead but since there could be multiple entry and exit transistions it
was clearer to use the entry/exit actions. Syntatic sugar sure, but
useful. You could also use events to announce the entry and exit and
then implement another state machine to set the flag but other than
increasing the size of the code and the execution time I don't see much
effect.

The incoming signals can indicate forward, reverse, neutral or be
invalid. The throttle can independantly be anywhere in its range. In a
complete example it could also be out of range but I did want a simple
example :) I also don't deal here with finite allowable tme to switch
directions, deadman switches and anti-tiedown logic :)

As a result of these the output could be forward, reverse, neutral or
stop.

My issue is: why can't the incoming signal be changeDirection rather
than an explicit Forward/Reverse couplet?


I suppose they could be but you would then still have to figure out
which direction it had changed to. I suppose you could generate
different events for each possibility but I think we've lost the
advantage at that point.

If one captures current direction in a state variable rather than in an
FSM state, then all one has is a toggle that is triggered by a single
event with no data packet. So I don't see a need for "different events".


Remember the incoming direction signal has four possible states. A
simple toggle won't work since from any specific diection indication you
could get any of the remaining three. So either you provide different
events for all possibilities or you pass in the new direction signal
information.

I didn't want to go here, but this was one of the things I was referring
to when I said I would do things differently; but it has nothing to do
with FSMs per se. In your example the Forward and Reverse data are
serving double duty. Certain combinations (both ON or both OFF) have
additional semantics unrelated to direction.
I think you've misunderstood the problem. The fact that direction
consists of four states is a consequence of the user interface not an
internal program design decision. This state machine is using the
signals from the user interface to determine the the signals that will
be fed to the actual motor control.

Whether neutral is considered a direction could be debated, personally I
think it's a good abstraction in the domain I use it in. It certainly
is distinct from forward or reverse and must be considered in any place
you consider forward and reverse. In any case all four states are
present, necessary and have to be dealt with.

That is very similar to return values being "normal" data when positive
and error codes when negative. Such semantic double duty can lead to
problems during maintenance (e.g., when requirements change and make
some negative values "normal" data or when your criteria for stopping
changes). IOW, separation of concerns applies to data domains are well
as behaviors.
I can understand why you would think that. It's not really the case
though. In that sense it's more akin to input validation.

I am with you on the separation of normal data from error codes. The
trouble is all four states are normal in a very real sense. Even if you
were to decide to treat the both directions selected as a separate event
you would still have three direction states.

I also have a problem with using them to trigger a transition to the
[Stop] state, which you said was an error state. Since they are input
alphabet values (i.e., part of the event data packet), what is being
checked is that consistent data is being provided.
As I said that's at least half the point of the state machine. It's not
checking for consistent data per se. The data is perfectly consistent
but something has caused an input that forces a return to stop. Note
that in a complete example more and different kinds of conditions can
cause a return to stop state.

If one is using DbC
for design, that should be a responsibility of whoever generates the
event. Thus it is a precondition of consuming the event that the data
in the data packet be consistent. IOW, when using DbC any assertions
made about the input data are checking the correctness of the software,
not the consistency of the data.

When the software becomes broken, that's a job for exception handling.
One might still need a [Stop] state for recovery, but getting there is a
job for the exception handler rather than FSM design.
Getting to stop is a function of working software not broken software.
Responding to faults is something the software must do and do correctly.
Think deadman switch or e-stop.

OK, seems an odd way to view it to me but I can see the equivalency.

Hmmm. I thought I was just mapping what you provided, so let me expand
on my analysis of the example...


I'm not disagreeing it just seems an odd viewpoint.

I guess it depends on where the observer is standing...
Almost always :)

OK. The separation into On-entry/during/on-exit (and transition actions
too) actions is still useful though. The code generator then picks up
the appropriate combination for each transistion. That would otherwise
have to be done by the designer. The computer is much better at
consistently doing that than I am.

My point here is that in your example I don't see any separation at all.
That is, I don't see a "during action". All I see is a simple Moore
FSM. The value of DriveRequest is always set in that <entry> action as
a direct result of consuming the event that triggered going to the state.
I understand. I'm just suggesting that like a for loop is a glorified
goto, the syntactic sugar is useful.

The only thing I see as unusual in the example is the way that way
transitions were selected. It is done within the statechart function
rather than in a spearate event queue or through a static class STT
lookup table.


STT?

State Transition Table.
Ah, I thought I'd seen the acronym before.

There are two forms. In one the table cells
are the event ID and the rows/columns are [current state, new state].
That is the one commonly seen in theoretical discussions. In the other
the cells are new state and the rows/columns are [current state, event
ID]. In practice the second form is used in software FSMs but the cells
are pointer-to-function for the specific state action. Then the event
queue can dispatch directly to the action when an event is popped.

No offense intended, but how often have you used FSMs?
Quite some time now. We just have a different educational background
that's all and since the code generator I've used for the last dozen
years or so doesn't use the construct or the acronymn is not near the
top of list of acronyms I recall. We do use the same language on
occasion to mean rather differnt things.

This is a very
basic acronym for FSMs and almost all FSMs are implemented using one for
efficiency.
Actually a very common technique in embedded systems is a table of
function pointers. One that a client has me maintain (I didn't design
it) uses a list of pointers to define possible transitions for each
state. Each transistion is defined by a pointer to condition function,
a pointer to an action function to be executed if the condition function
returns true and a pointer to the next state if the transistion is taken
(the condition returns true). If the next state is null the state
doesn't change. And what happens? You can probably guess at his point.
The conditions functions actually perform actions in some cases.

I was already suspicious that you don't use a lot because
you used the "statechart function" to implement the event with embedded
processing for the conditional event dispatch. I had never seen anyone
do that before. B-) BTW, the two most common ways for implementing
software FSMs are the GoF State pattern (where the STT is used to
dynamically instantiate the relationship between Context and State) and
utilizing a reusable event queue infrastructure.

[All commercial full code generators employ the event queue
infrastructure.
Not all of them, the one I use doesn't. It uses that function call. A
lot of state machines I've seen use some variation on that. Some use
tables of function pointers, some use other constructs. There are
actually reasons you might not want tables of constant values in some
embedded systems.

I suppose you could convert all the conditional checks by running them
externally and producing event ids for each one. Seems a lot of work
just get get a abstract ID though. The other disadvantage I see with
that is the actual condition is now several steps removed from the
transition it causes.

Not necessarily. Recall my model for Motor. It was actually somewhat
simpler than your model. Its actions could do everything you said were
done in your FSM actions and its transitions enforced the same
sequencing rules that yours did.
No it didn't. It failed on two accounts. It never returned to stop and
it didn't have any forward/reverse assymetry (admittedly a later
clarification). It didn't even have a stop state, just a neutral state.

It also excluded the event generation.

It just did it with different
conditions (states), events, and state variables.

I think the condition is only one step removed.
Instead of
call statechart
check condition

you have
check condition
generate event
call statechart

I count an extra step. More if you include the fact you are now check
more conditions than necessary for a given state.

The DbC precondition
for executing any state action exactly matches the postcondition of some
other action (i.e., the one where the event is generated to announce
that its postcondition prevails).
Exactly as in the case of using a simple conditional check.

So far I don't see the abstract IDs as any simpler than the conditional
check. Actually I don't see that they are not fundamentally identical
unless you have something running around changing values behind the
state machines back which would be bad design practice IMO.

Why is
if( a < DFG ) {
QueueEvent(queue, QW);
}
if( b == GHJZZ ) {
QueueEvent(queue, QE);
}
StateChart( queue, out);

superior to
StateChart( a, b, out);

There are several reasons. From an aesthetic perspective the FSM
provides /invariant/ constraints on /relative/ sequencing. They should
be invariant relative to the external context.
And how are the constraints I'm using less invariant than events?

However, 'a' and 'b' are
external context variables. If one moves the conditional dispatch into
the FSM, one is making the FSM context-dependent and increases the
probability of maintenance problems.
I don't see that. I'm not saying there aren't cases where events are a
better represenation, I think there are. It's just in the cases I
usually deal with using conditional checks is simpler and more obviously
correct.

There are two ways the FSM can utilize context variables. The FSM
actions can access them parametrically for a computation within a state
action. That usage is well constrained with respect to scope.
OK so why wouldn't conditions based on those same values be well
constrained?

The other thing they can affect is the sequencing of actions within the
FSM. That is essentially what conditional events do; they use context
variables to change the structure of the FSM on the fly.
No more than events do.

To me that is
kind of like an assigned GOTO in FORTRAN; it opens all sorts of
opportunities for unexpected side affects. IOW when one changes the
data semantics of the state variables one not only needs to worry about
what one computes from the data but which formula one uses to do the
computation.
That's sort of the point. The result depends on the state you are in.
If you don't compute it there you have to have knowledge of which state
the state machine is in externally when you compute it. As far as I'm
concerned that opens the inner workings of the state machine to external
view too much. The during actions express that clearly and directly.

That is an issue of separation of concerns. The FSM structure is
inherently static. Modifying transitions dynamically adds another
dimension of complexity to the FSM structure and that is probably not a
good idea.
Who's modifying transistions dynamically?

One way that is manifested is in the notion of OO announcement messages
(I'm Done) compared to procedural imperative messages (Do This). The
event being generated announces a change in condition /outside/ the FSM.
That is, the event itself is announcing something happening
externally. As it happens that depends upon 'a' and 'b'. But it
announces a compound condition that also includes whatever the caller
did. IOW, the condition being announced is {(a < DFG), caller completed
its part of the solution} OR {(b == GHJZZ), caller completed its part of
the solution}.
Or just as likely both. The state machine then has to discard the
irrelevant events.

More importantly, it includes a context decision that the IF statements
themselves define. Those IF statements implement problem space rules
and policies to determine exactly What should be announced.
Beg pardon? I think you are envisioning an entirely different kind of
problem than I am. The state machine must be aware of all the inputs
(or events) anything else would be unsafe. The only way anything
external to the state machine could filter the events/data to a subset
would be if it were aware of the state it was in.

The FSM
only responds to the announcement. If one moves the IF statements into
the FSM itself, one is moving that external context decision into the
FSM. That external context decision probably isn't any of the FSM's
business; it should just respond to the decision's /result/.
?? That external context is the entire reason for the state machine to
exist. Having said that the external context may be abstracted or
idealized. The direction input could be a single multivalued input
rather than a pair of flags as a for instance.

Finally, when managing complexity it is wise to isolate related rules
and policies via encapsulation. It is highly unlikely that the rules
and policies that determine what event to generate will be logically
related to the rules and policies that the FSM exists to resolve. So if
one moves those rules and policies into the FSM, one is trashing the
cohesion of the FSM.
While there is a lot to encapsulation and isolation it is quite possible
to take it too far. Data and actions that are tightly coupled should
not be separated.

The bottom line is that the software will be more maintainable if one
decouples message and method, separates concerns, and encapsulates rules
and policies in a cohesive fashion. Superficially both your examples do
the same thing. But devil is in the details and from the perspective of
maintainability there are potentially huge differences when one gets to
the details.
Actually, encapsulation is a big reason for choosing the form I use in
the example rather than an event queue. All of the logic for
determining the requested drive signal is isolated to the state machine.

Robert

--
From the Divided by a Common Language File (Edited to protect the
guilty)
ME - "I'd like to get Price and delivery for connector Part # XXXXX"
Dist./Rep - "$X.XX Lead time 37 days"
ME - "Anything we can do about lead time? 37 days seems a bit high."
Dist./Rep - "that is the lead time given because our stock is live....
we currently have stock."


--
Posted via a free Usenet account from http://www.teranews.com
 
Responding to Adsett...

In a software FSM a state represents a condition where a unique set of
rules and policies prevails. A corollary is that the rules and policies
in that set will be cohesive. I believe this is important because it
can affect subsequent maintenance. Suppose we originally have

|
| E1:prepare
V
[Prepared]
|
| E2:start
V
[Running]

where the [Prepared] state has an entry action to lubricate and an exit
action to start cooling.

Now consider what happens when requirements change such that cooling is
triggered by a temperature sensor. Now cooling is triggered after the
motor is running rather than before. So one might introduce a new state
and transition:


I'd use a different state machine in that case. Since it would be truly
independant of the machine operating state. For the kind of state
dependance I'm referring to this kind of change would be rare. It would
require changing the machine, a much more daunting task than modifying
the state machine. Even if it is likely the simplicity of viewing the
behaviour is a single state machine is, in this case, an advantage.
Once the behaviour is no longer dependant on the state the
multiplicitive increase in states alone makes a separate state machine
attractive. More to the point it matches the problem domain.
I was assuming that lubricating, starting, and cooling were all hardware
facilities. That is, the rules and policies for controlling each one
involved the same register reads and writes whether one decided to cool
as part of startup or based on running temperature. IOW, the code in
the actions would be exactly the same.

As far as mapping the the problem space is concerned, it seems to me
that placing lubricating and cooling as entry/exit actions in a single
state like [Prepared] is constructing the FSM around a preconceived view
of the solution rather than the invariants of the problem space. Once
one accepts the notion that controlling lubrication is a quite different
responsibility than controlling cooling, it seems reasonable to
associate those unique rules and policies with their own states. When
the motor is lubricated it is in a state where it is ready to run. When
the motor is cooled it is in a state where the the cooling mechanisms
are activated. And when it has been started it is a state where it has
been powered up.

Those conditions all seem quite natural in the problem space and they
are intrinsic states of the Motor that do not depend on the order in
which the hardware elements are controlled. That ordering can then be
expressed in terms of transitions between those states. So if one
isolated those actions with the problem space states, one could reorder
the sequence by simply rearranging the transitions when requirements
provided a different order. IOW, there is no need for new states; they
were already in the problem space and one has simply reordered their
sequence.

Also it's not as if creating an additional state machine at that point
is difficult, it's a small addition to the work needed to add the new
temperature input. One thing to remember is we are not dealing with a
general purpose library here, these behaviours tend to be specific to
the application environment and if a behaviour is tightly coupled to a
state it's very likely to remain so.
Any time one touches the software there is an opportunity for breaking
it by inserting a defect. The probability of inserting a defect tends
to increase for data changes -> static structure changes -> behaviors.
So a major goal of modern software development (and the OO paradigm in
particular) is to minimize the number of places one touches the software
to implement changes while making changes in places that are less likely
to become broken by the change.

In this case I would much rather use the same states and actions than
add a state even though the action could be cut & pasted. I don't want
to touch the actions in any way if I can avoid it. I don't want to
substantially change the static structure by adding states if I can
avoid it. If it were feasible to do the change in configuration data
without touching the transitions, I would do that instead.

[I have a great horror story about about a one-line cut&paste of a
single call that resulted in a Group VP being berated for half an hour
on the phone by an irate customer CEO. As a developer, one does not
want that kind of visibility. I use the OO paradigm because I want to
minimize the possibility of that kind of visibility -- even for changes
that "aren't that difficult". Isolating lubrication and cooling in
their own problem space states does that; artificially making them entry
and exit actions in the same state because that's more convenient for
the original solution doesn't.]

The most recent occaision I've had reason for using that coupled on-
entry/on-exit construct was for flagging a fault state. On entry to the
fault state the flag would be set, on exit it would be cleared. You
could do the same thing by performing the action on the transitions
instead but since there could be multiple entry and exit transistions it
was clearer to use the entry/exit actions. Syntatic sugar sure, but
useful. You could also use events to announce the entry and exit and
then implement another state machine to set the flag but other than
increasing the size of the code and the execution time I don't see much
effect.
As you may recall, I already said I don't have that big a problem with
exit actions per se on a case-by-case basis. I just feel one should
understand the trade-off for maintenance risk and that trade-off rarely
comes out in favor of exit actions.

The incoming signals can indicate forward, reverse, neutral or be
invalid. The throttle can independantly be anywhere in its range. In a
complete example it could also be out of range but I did want a simple
example :) I also don't deal here with finite allowable tme to switch
directions, deadman switches and anti-tiedown logic :)

As a result of these the output could be forward, reverse, neutral or
stop.

My issue is: why can't the incoming signal be changeDirection rather
than an explicit Forward/Reverse couplet?


I suppose they could be but you would then still have to figure out
which direction it had changed to. I suppose you could generate
different events for each possibility but I think we've lost the
advantage at that point.

If one captures current direction in a state variable rather than in an
FSM state, then all one has is a toggle that is triggered by a single
event with no data packet. So I don't see a need for "different events".


Remember the incoming direction signal has four possible states. A
simple toggle won't work since from any specific diection indication you
could get any of the remaining three. So either you provide different
events for all possibilities or you pass in the new direction signal
information.

I didn't want to go here, but this was one of the things I was referring
to when I said I would do things differently; but it has nothing to do
with FSMs per se. In your example the Forward and Reverse data are
serving double duty. Certain combinations (both ON or both OFF) have
additional semantics unrelated to direction.


I think you've misunderstood the problem. The fact that direction
consists of four states is a consequence of the user interface not an
internal program design decision. This state machine is using the
signals from the user interface to determine the the signals that will
be fed to the actual motor control.
I can't buy that. The UI is a separate subsystem whose job is to
convert the user view to the problem solution view. Using ON/ON and
OFF/OFF combinations in the interface between the UI and the problem
solution is a matter of interface design. The interfaces to the problem
solution's subsystems are under the developer's control. Even if the UI
wants to export ON/ON and OFF/OFF, each subsystem has its own two-way
interface and one can deal the problem in the glue code between them.
So my pushback would be to fix those interfaces.

That is very similar to return values being "normal" data when positive
and error codes when negative. Such semantic double duty can lead to
problems during maintenance (e.g., when requirements change and make
some negative values "normal" data or when your criteria for stopping
changes). IOW, separation of concerns applies to data domains are well
as behaviors.


I can understand why you would think that. It's not really the case
though. In that sense it's more akin to input validation.

I am with you on the separation of normal data from error codes. The
trouble is all four states are normal in a very real sense. Even if you
were to decide to treat the both directions selected as a separate event
you would still have three direction states.
I still think it's still double duty; its is just spread over two data
domains.

Forward ON; Reverse OFF. Redundantly specifies forward operation
Forward OFF; Reverse ON. Redundantly specifies reverse operation
Forward ON; Reverse ON. An input error.
Forward OFF; Reverse OFF. The motor goes to neutral.

Clearly fielding an input error in the UI has nothing to do with the
notions of forward and reverse operation. That's the UI's job and
shouldn't even be an issue in the controller context except, possibly,
as a DbC assertion for the interface to the UI. That is pretty much
exactly what using negative numbers for error codes on return values does.

Similarly, the notion of neutral really isn't the same as NOT forward
AND NOT reverse. That is manifested in the redundancy when specifying
when the motor really is operating in forward or reverse. What is
needed is to separate the semantics of direction vs. running, as in:

Forward ON. Specifies forward operation, if running
Forward OFF. Specifies reverse operation, if running
Powered ON. Specifies motor is powered
Powered OFF. Specifies motor is not powered

There are still two state variables and four combinations of values.
But the semantics have been properly decoupled in the variable data
domains so that they can be assigned independently.

I also have a problem with using them to trigger a transition to the
[Stop] state, which you said was an error state. Since they are input
alphabet values (i.e., part of the event data packet), what is being
checked is that consistent data is being provided.


As I said that's at least half the point of the state machine. It's not
checking for consistent data per se. The data is perfectly consistent
but something has caused an input that forces a return to stop. Note
that in a complete example more and different kinds of conditions can
cause a return to stop state.
You indicated [Stop] was an error state. That's fine. But getting
there should be triggered by an event that is raised explicitly by
detecting the error condition _outside the FSM_. The FSM /responds/ to
changes in the application state by switching states.

IOW, generating the error event may be conditional based on state
variables, but there is nothing conditional about the FSM's transition
once that condition prevails. In this case I think the UI should check
the input values and generate the appropriate event if you really want
the motor to respond that way. If some other external situation also
triggers a reset to the error state, whoever detects that condition
should generate the appropriate event. It isn't up the the FSM to
detect error conditions in the state of the application (e.g., user
input errors); the FSM just responds appropriately when such conditions
prevail by consuming the triggering event.

If one is using DbC
for design, that should be a responsibility of whoever generates the
event. Thus it is a precondition of consuming the event that the data
in the data packet be consistent. IOW, when using DbC any assertions
made about the input data are checking the correctness of the software,
not the consistency of the data.

When the software becomes broken, that's a job for exception handling.
One might still need a [Stop] state for recovery, but getting there is a
job for the exception handler rather than FSM design.


Getting to stop is a function of working software not broken software.
Responding to faults is something the software must do and do correctly.
Think deadman switch or e-stop.
You indicated that going to the Stop state was the result of
inconsistent user input data for the directions and that is the case I
am addressing. I don't care how many other ways there may be to get to
the Stop state; I am only interested in the FSM structure around this
path. I submit that such an error should have been detected by the UI
so that it never reaches the FSM. In that case, any DbC check by the
FSM is a check on the correctness of the software in not allowing such
an inconsistency to reach it.

If there is a reason for the motor to go to the stop state when the user
supplies inconsistent data, that is a quite different thing. In that
situation the UI should generate an event to announce the inconsistency
and the FSM should respond to that event by unconditionally
transitioning to the Stop state.

OK. The separation into On-entry/during/on-exit (and transition actions
too) actions is still useful though. The code generator then picks up
the appropriate combination for each transistion. That would otherwise
have to be done by the designer. The computer is much better at
consistently doing that than I am.

My point here is that in your example I don't see any separation at all.
That is, I don't see a "during action". All I see is a simple Moore
FSM. The value of DriveRequest is always set in that <entry> action as
a direct result of consuming the event that triggered going to the state.


I understand. I'm just suggesting that like a for loop is a glorified
goto, the syntactic sugar is useful.
OK. But the last 200 or so messages were triggered by the notion of
having a "during action". B-)

There are two forms. In one the table cells
are the event ID and the rows/columns are [current state, new state].
That is the one commonly seen in theoretical discussions. In the other
the cells are new state and the rows/columns are [current state, event
ID]. In practice the second form is used in software FSMs but the cells
are pointer-to-function for the specific state action. Then the event
queue can dispatch directly to the action when an event is popped.

No offense intended, but how often have you used FSMs?


Quite some time now. We just have a different educational background
that's all and since the code generator I've used for the last dozen
years or so doesn't use the construct or the acronymn is not near the
top of list of acronyms I recall. We do use the same language on
occasion to mean rather differnt things.


This is a very
basic acronym for FSMs and almost all FSMs are implemented using one for
efficiency.


Actually a very common technique in embedded systems is a table of
function pointers. One that a client has me maintain (I didn't design
it) uses a list of pointers to define possible transitions for each
state. Each transistion is defined by a pointer to condition function,
a pointer to an action function to be executed if the condition function
returns true and a pointer to the next state if the transistion is taken
(the condition returns true). If the next state is null the state
doesn't change. And what happens? You can probably guess at his point.
The conditions functions actually perform actions in some cases.
That table of function pointers is basically the second form of STT that
I mentioned above. The condition function is just the sort of
indirection overhead one gets into if one supports the /possibility/ of
conditional relationships. If one doesn't use conditional relationships
the table just contains the action pointers. (Of course if one also
might have exit actions, one needs yet another table.)

[All commercial full code generators employ the event queue
infrastructure.


Not all of them, the one I use doesn't. It uses that function call. A
lot of state machines I've seen use some variation on that. Some use
tables of function pointers, some use other constructs. There are
actually reasons you might not want tables of constant values in some
embedded systems.
Just out of curiosity, which one is that? I thought I knew all the full
code generators for UML (Pathfinder is one of the vendors).

[BTW, PathMATE happens to support both conditional transitions and exit
actions. It uses event queues and STT dispatch for any asynchronous
implementation. PathMATE's primary market niche is high performance
R-T/E, which might say something about the performance merits. B-)]

I suppose you could convert all the conditional checks by running them
externally and producing event ids for each one. Seems a lot of work
just get get a abstract ID though. The other disadvantage I see with
that is the actual condition is now several steps removed from the
transition it causes.

Not necessarily. Recall my model for Motor. It was actually somewhat
simpler than your model. Its actions could do everything you said were
done in your FSM actions and its transitions enforced the same
sequencing rules that yours did.


No it didn't. It failed on two accounts. It never returned to stop and
it didn't have any forward/reverse assymetry (admittedly a later
clarification). It didn't even have a stop state, just a neutral state.
That's because in your original FSM description Stop didn't do anything
except set DriveRequest to 0, which was what Neutral did. When I
changed the state variable and other semantics it was no longer needed.
It did return to Neutral under all the same <substantive> conditions
that you originally specified (or I inferred).

Now you can argue that your original FSM was designed your way because
of other, unmentioned requirements. But that's a different FSM. My
counter is that if those requirements were mentioned and your full FSM
was drawn, I could probably still come up with a simpler version -- if
for no other reason than eliminating the conditional transitions. B-)

It also excluded the event generation.
I am not sure what this means. You FSM didn't have any event generation
either; it just selected transitions given an event. Do you mean I
didn't have conditional transitions? If so, that came with changing the
semantics of the state variables and events.

It just did it with different
conditions (states), events, and state variables.

I think the condition is only one step removed.


Instead of
call statechart
check condition
You forgot the last step: select a transition. That is equivalent to
generating an event below.

you have
check condition
generate event
call statechart

I count an extra step. More if you include the fact you are now check
more conditions than necessary for a given state.
The point is that somebody always detects a condition and announces it
with an event. The FSM always responds to that announcement event by
transitioning to a new state and executing the associated action. That
is about as peer-to-peer as the collaboration can get without bleeding
cohesion between the FSM and the external environment.

When has a condition check that determines the transition inside the
FSM, one is bleeding cohesion because the FSM is doing part of the job
that the <external> event generator should be doing. Part of the
detection (the trigger event) is outside the FSM and part is inside
(selecting a transition). IOW, detecting condition changes is one thing
while responding to them is quite another and I think those two concerns
should be separated.

The DbC precondition
for executing any state action exactly matches the postcondition of some
other action (i.e., the one where the event is generated to announce
that its postcondition prevails).


Exactly as in the case of using a simple conditional check.
The problem lies in who owns the condition check (more precisely, who
owns which pieces of a compound condition check), per the point
immediately above.

So far I don't see the abstract IDs as any simpler than the conditional
check. Actually I don't see that they are not fundamentally identical
unless you have something running around changing values behind the
state machines back which would be bad design practice IMO.

Why is
if( a < DFG ) {
QueueEvent(queue, QW);
}
if( b == GHJZZ ) {
QueueEvent(queue, QE);
}
StateChart( queue, out);

superior to
StateChart( a, b, out);

There are several reasons. From an aesthetic perspective the FSM
provides /invariant/ constraints on /relative/ sequencing. They should
be invariant relative to the external context.


And how are the constraints I'm using less invariant than events?
They depend upon specific state variable values. The FSM doesn't care
about the specific values; it only cares that /some/ condition announced
by QW or QE exists. The sequencing constraints in the FSM define
intrinsic constraints on when the state actions can be performed
relative to one another without regard to solution context. The
constraints on 'a' and 'b' represent a mapping of intrinsic FSM
sequencing constraints to specific context semantics in the overall
problem solution. That mapping to solution specifics is none of the
FSM's concern.

Suppose there is another object with a method that does something like:

if (x > ABC)
QueueEvent (queue, QW)
if (y != LMNOP)
QueueEvent (queue, QE)
StatrChart (queue, out)

Here have have exactly the same events triggering the same actions in
the same FSM. But the local context semantics is quite different. If
one moves the conditions on 'a', 'b', 'x', and 'y' into transition
conditions within the FSM, one starts to lose the significance of the
local context in the complexity of the <now compound> conditions on the
transitions. OTOH, if one keeps the two sets of conditions encapsulated
in different objects each context is much clearer. (Each is isolated
and each is explicitly linked to the broader semantic contexts where DFG
and ABC are meaningful.)

More important, when only one of those detailed contexts changes, one
just touches that context. The other context and the FSM remains
untouched as it still responds to QW and QE in exactly the same way. IN
addition, one can add an entirely new context to collaborate with the
same FSM without touching the FSM.

However, 'a' and 'b' are
external context variables. If one moves the conditional dispatch into
the FSM, one is making the FSM context-dependent and increases the
probability of maintenance problems.


I don't see that. I'm not saying there aren't cases where events are a
better represenation, I think there are. It's just in the cases I
usually deal with using conditional checks is simpler and more obviously
correct.
The condition checks are going to be exactly the same in either case.
The issue is about who should own them. I submit that since the
specific conditions represent a mapping of the intrinsic (invariant)
internal FSM sequencing constraints into the semantics of specific
problem contexts, those conditions should be owned by someone outside
the FSM who understands the local context.

There are two ways the FSM can utilize context variables. The FSM
actions can access them parametrically for a computation within a state
action. That usage is well constrained with respect to scope.


OK so why wouldn't conditions based on those same values be well
constrained?
I am talking about data integrity scope here. One can manage things
like thread pausing and whatnot easier if scope is defined by a single
procedure. Similarly, one can focus on the design issues better if
scope of data access is limited to single method scope.

The other thing they can affect is the sequencing of actions within the
FSM. That is essentially what conditional events do; they use context
variables to change the structure of the FSM on the fly.


No more than events do.
Very much more so! If there are no conditional transitions the
structure and sequencing of the FSM for the incoming events is
completely invariant. It depends solely on {event ID, current state}.
No matter how many times that tuple is processed, the path is exactly
the same each time.

However, if there are conditional transitions the structure is
effectively modified. Instead of one possible path for a given event
and current state there are multiple paths that depend upon {event ID,
current state, state var1, state var2, ...}. Thus the structure of the
FSM itself is potentially different each time that {event ID, current
state, ...} tuple is processed. To put it another way, if one drew the
FSM as if only one condition existed, it would have a different
structure than if one drew it for only one of the other conditions.

To me that is
kind of like an assigned GOTO in FORTRAN; it opens all sorts of
opportunities for unexpected side affects. IOW when one changes the
data semantics of the state variables one not only needs to worry about
what one computes from the data but which formula one uses to do the
computation.


That's sort of the point. The result depends on the state you are in.
If you don't compute it there you have to have knowledge of which state
the state machine is in externally when you compute it. As far as I'm
concerned that opens the inner workings of the state machine to external
view too much. The during actions express that clearly and directly.
When there are no conditional transitions, one /always/ knows exactly
what path will be taken for a given {event ID, current state} tuple,
regardless of what might be happening in the overall solution. As soon
as one starts to make the path variable, one has an assigned GOTO where
the assignment is done outside the FSM.

Those state variables one is using to select transitions are defined and
assigned outside the FSM. They represent external context. So one is
bleeding that context into the FSM, which makes the FSM more complex.
It also splits up compound conditions between whoever generates the
triggering event and the FSM itself. (Somebody still has to know it is
time to generate an event to the FSM.)

However, if one encapsulates all the semantics of the local solution
context all in one place, one has good separation of concerns and that
aids in managing the complexity. The condition for transition to a
particular state has to be detected somewhere. To me the issue is
whether one should encapsulate those detection rules and policies in one
place that logically should understand them or split them up over two
objects, one of which don't have a logical need to know about the context.

That is an issue of separation of concerns. The FSM structure is
inherently static. Modifying transitions dynamically adds another
dimension of complexity to the FSM structure and that is probably not a
good idea.


Who's modifying transistions dynamically?
You are any time you modify the state variable used to select a
conditional transition during the life of the FSM.

One way that is manifested is in the notion of OO announcement messages
(I'm Done) compared to procedural imperative messages (Do This). The
event being generated announces a change in condition /outside/ the FSM.
That is, the event itself is announcing something happening
externally. As it happens that depends upon 'a' and 'b'. But it
announces a compound condition that also includes whatever the caller
did. IOW, the condition being announced is {(a < DFG), caller completed
its part of the solution} OR {(b == GHJZZ), caller completed its part of
the solution}.


Or just as likely both. The state machine then has to discard the
irrelevant events.
I think ignoring events in the STT is a quite different thing than
conditional transitions. There is no law that requires one to do
something in response to raising a condition, so it is valid to ignore
certain events when the FSM is in a particular state.

The issue here is choosing a transition path from among alternatives
_when the event cannot be ignored_.

More importantly, it includes a context decision that the IF statements
themselves define. Those IF statements implement problem space rules
and policies to determine exactly What should be announced.


Beg pardon? I think you are envisioning an entirely different kind of
problem than I am. The state machine must be aware of all the inputs
(or events) anything else would be unsafe. The only way anything
external to the state machine could filter the events/data to a subset
would be if it were aware of the state it was in.
The FSM only needs to be aware of events and the relevant input alphabet
for a transition that is processed by the corresponding action. That's
all an FSM does: it responds to events by processing the the input alphabet.

My point here is when you select a transition you are defining a
particular state for the FSM (i.e., the target state for the selected
transition). The precondition for entering that state is a compound
condition composed of:

- the postcondition of the action the generated the trigger event

- any data integrity constraints on state variables to be accessed by
the action

- the conditions used to select the transition.

IOW, the conditions used to select the transition are necessarily part
of the precondition for entering the target state. If they did not
evaluate TRUE, transitioning to that state would be inappropriate.

The primary issue of this whole subdiscussion is whether that
precondition should be evaluated in one place or in two places.

The FSM
only responds to the announcement. If one moves the IF statements into
the FSM itself, one is moving that external context decision into the
FSM. That external context decision probably isn't any of the FSM's
business; it should just respond to the decision's /result/.


?? That external context is the entire reason for the state machine to
exist. Having said that the external context may be abstracted or
idealized. The direction input could be a single multivalued input
rather than a pair of flags as a for instance.
The state variables being tested /are/ the external context. Forward
and Reverse or 'a' and 'b' in your examples have their values assigned
based upon conditions that exist outside the FSM. They have semantics
that is defined in terms of that external context.

I am arguing that such external context should be evaluated externally
(preferably in one place) and an appropriate event generated to the FSM
based on that evaluation. If one always encapsulates the rules and
policies for detecting state changes that way in a place that logically
understands the context semantics, one never needs conditional events in
the receiver FSMs.

Finally, when managing complexity it is wise to isolate related rules
and policies via encapsulation. It is highly unlikely that the rules
and policies that determine what event to generate will be logically
related to the rules and policies that the FSM exists to resolve. So if
one moves those rules and policies into the FSM, one is trashing the
cohesion of the FSM.


While there is a lot to encapsulation and isolation it is quite possible
to take it too far. Data and actions that are tightly coupled should
not be separated.
True. That's why one needs a design methodology to draw the lines in
the sand. The OO paradigm draws lines in the sand based on problem
space abstraction while Structured Programming drew them based upon
functional decomposition.

But I would still argue that the rules and policies for detecting state
changes are going to be quite different than those that govern the
response to state changes, regardless of what methodology one uses. B-)

The bottom line is that the software will be more maintainable if one
decouples message and method, separates concerns, and encapsulates rules
and policies in a cohesive fashion. Superficially both your examples do
the same thing. But devil is in the details and from the perspective of
maintainability there are potentially huge differences when one gets to
the details.


Actually, encapsulation is a big reason for choosing the form I use in
the example rather than an event queue. All of the logic for
determining the requested drive signal is isolated to the state machine.
And this is a core disagreement. To me conditional transitions
represent lack of cohesion and poor separation of concerns.


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
 
In article <IYfnh.5273$SQ1.4549@trnddc03>, H. S. Lahman says...
Responding to Adsett...

In a software FSM a state represents a condition where a unique set of
rules and policies prevails. A corollary is that the rules and policies
in that set will be cohesive. I believe this is important because it
can affect subsequent maintenance. Suppose we originally have

|
| E1:prepare
V
[Prepared]
|
| E2:start
V
[Running]

where the [Prepared] state has an entry action to lubricate and an exit
action to start cooling.

Now consider what happens when requirements change such that cooling is
triggered by a temperature sensor. Now cooling is triggered after the
motor is running rather than before. So one might introduce a new state
and transition:


I'd use a different state machine in that case. Since it would be truly
independant of the machine operating state. For the kind of state
dependance I'm referring to this kind of change would be rare. It would
require changing the machine, a much more daunting task than modifying
the state machine. Even if it is likely the simplicity of viewing the
behaviour is a single state machine is, in this case, an advantage.
Once the behaviour is no longer dependant on the state the
multiplicitive increase in states alone makes a separate state machine
attractive. More to the point it matches the problem domain.

I was assuming that lubricating, starting, and cooling were all hardware
facilities. That is, the rules and policies for controlling each one
involved the same register reads and writes whether one decided to cool
as part of startup or based on running temperature. IOW, the code in
the actions would be exactly the same.
I expect it would be, but adding temperature sensing would not be a
small task. That's my point here, for many of these choices to use on-
entry/on-exit actions in this fashion the hardware limitations have
already restricted the possibles places to perform the action to places
where the machine state is well known. Adding a separate state machine
just adds a level of indirection, reducing clarity. Having a state
machine whose only purpose is to turn something on when another state
machine enters a state and to turn it off again when it exits that state
seems a little over done.

As I said it the machine is change dto be independant of the operating
state (such as to become dependent on the temperature) then it's time to
create a separate state machine.

As far as mapping the the problem space is concerned, it seems to me
that placing lubricating and cooling as entry/exit actions in a single
state like [Prepared] is constructing the FSM around a preconceived view
of the solution rather than the invariants of the problem space.
You still misunderstand. Lubrication on would be the on-entry action of
[running], lubrication off would be the on-exit action of [running].
Cooling doesn't get involved anywhere, it was a separate example.

Once
one accepts the notion that controlling lubrication is a quite different
responsibility than controlling cooling,
I thought I'd already pointed out that I wasn't considering them
dependent, that they were two different examples.

Also it's not as if creating an additional state machine at that point
is difficult, it's a small addition to the work needed to add the new
temperature input. One thing to remember is we are not dealing with a
general purpose library here, these behaviours tend to be specific to
the application environment and if a behaviour is tightly coupled to a
state it's very likely to remain so.

Any time one touches the software there is an opportunity for breaking
it by inserting a defect.
Absolutely, but I don't see that creating an additional state machine is
any more error prone later rather than sooner.

The most recent occaision I've had reason for using that coupled on-
entry/on-exit construct was for flagging a fault state. On entry to the
fault state the flag would be set, on exit it would be cleared. You
could do the same thing by performing the action on the transitions
instead but since there could be multiple entry and exit transistions it
was clearer to use the entry/exit actions. Syntatic sugar sure, but
useful. You could also use events to announce the entry and exit and
then implement another state machine to set the flag but other than
increasing the size of the code and the execution time I don't see much
effect.

As you may recall, I already said I don't have that big a problem with
exit actions per se on a case-by-case basis. I just feel one should
understand the trade-off for maintenance risk and that trade-off rarely
comes out in favor of exit actions.
OK, but this example is identical to the lubrication example you are
objecting to.

Remember the incoming direction signal has four possible states. A
simple toggle won't work since from any specific diection indication you
could get any of the remaining three. So either you provide different
events for all possibilities or you pass in the new direction signal
information.

I didn't want to go here, but this was one of the things I was referring
to when I said I would do things differently; but it has nothing to do
with FSMs per se. In your example the Forward and Reverse data are
serving double duty. Certain combinations (both ON or both OFF) have
additional semantics unrelated to direction.


I think you've misunderstood the problem. The fact that direction
consists of four states is a consequence of the user interface not an
internal program design decision. This state machine is using the
signals from the user interface to determine the the signals that will
be fed to the actual motor control.

I can't buy that. The UI is a separate subsystem whose job is to
convert the user view to the problem solution view. Using ON/ON and
OFF/OFF combinations in the interface between the UI and the problem
solution is a matter of interface design. The interfaces to the problem
solution's subsystems are under the developer's control. Even if the UI
wants to export ON/ON and OFF/OFF, each subsystem has its own two-way
interface and one can deal the problem in the glue code between them.
So my pushback would be to fix those interfaces.
As I said I think you've misunderstood the problem. This example does
not simply receive information from the UI it provides the proper
behaviour for the UI. It is providing the safety interlocks. And the
input neutral is definitely distinct from forward and reverse.

That is very similar to return values being "normal" data when positive
and error codes when negative. Such semantic double duty can lead to
problems during maintenance (e.g., when requirements change and make
some negative values "normal" data or when your criteria for stopping
changes). IOW, separation of concerns applies to data domains are well
as behaviors.


I can understand why you would think that. It's not really the case
though. In that sense it's more akin to input validation.

I am with you on the separation of normal data from error codes. The
trouble is all four states are normal in a very real sense. Even if you
were to decide to treat the both directions selected as a separate event
you would still have three direction states.

I still think it's still double duty; its is just spread over two data
domains.

Forward ON; Reverse OFF. Redundantly specifies forward operation
Forward OFF; Reverse ON. Redundantly specifies reverse operation
Yes

Forward ON; Reverse ON. An input error.
Sort of. As I said think deadman switch or e-stop as well. I won't
object if you want to consider it separately though.

Forward OFF; Reverse OFF. The motor goes to neutral.
No. The input state goes to stop, what the motor does is beyond this
example. Typically the motor will indeed follow, probably to a neutral
state or something similar but there are likely to be lags.

Don't get too hung up on this. Remember I said this was a simplified
example. This input although it exists serves also to stand-in for all
the other possible ways you get back to the stop state.

Clearly fielding an input error in the UI has nothing to do with the
notions of forward and reverse operation.
That's true, but it does have to do with what the requested motor output
should be. As I said in the previous message look at it as e-stop or
deadman, it's not an input error in the sense the user should retype in
a value, it's an error in the sense that a safety sequence has been
violated. The input state MUST (it's a requirement) go back to the stop
state and go through the start sequencing before it can re-enter neutral
and select a direction.


That's the UI's job and
shouldn't even be an issue in the controller context except, possibly,
as a DbC assertion for the interface to the UI.
No. It is very much the job of this routine. This is where it's
determined that the operator has satisfied the required conditions for
proceeding. The actual motor control is decoupled from this as it
should be.

If it helps, consider it part of the UI, after all it's about ensuring
the operator has satisfied the input requirements and then generating
the appropriate output to go to the motor control.

Similarly, the notion of neutral really isn't the same as NOT forward
AND NOT reverse. That is manifested in the redundancy when specifying
when the motor really is operating in forward or reverse. What is
needed is to separate the semantics of direction vs. running, as in:

Forward ON. Specifies forward operation, if running
Forward OFF. Specifies reverse operation, if running
And neutral which is different. A motor can be powered but not in
either forward and reverse. If you don't believe me try operating an
automobile without using neutral.

More to the point since this state machine does not deal with the motor
but the input to the motor, neutral is a distinct input state. The
operator can distinctly specify neutral and will.

Powered ON. Specifies motor is powered
Powered OFF. Specifies motor is not powered
Generally if the motor (controller) is not powered you won't even get
this far. Error checking during startup should ensure that. Also you
are confusing the motor state with the input state this state machine is
providing. The motors own control and states are separate from this
state machine.

There are still two state variables and four combinations of values.
They are, however, the wrong ones.

I also have a problem with using them to trigger a transition to the
[Stop] state, which you said was an error state. Since they are input
alphabet values (i.e., part of the event data packet), what is being
checked is that consistent data is being provided.


As I said that's at least half the point of the state machine. It's not
checking for consistent data per se. The data is perfectly consistent
but something has caused an input that forces a return to stop. Note
that in a complete example more and different kinds of conditions can
cause a return to stop state.

You indicated [Stop] was an error state. That's fine. But getting
there should be triggered by an event that is raised explicitly by
detecting the error condition _outside the FSM_. The FSM /responds/ to
changes in the application state by switching states.
That's exactly what it is doing, responding to changes in the
application state by switching states.

IOW, generating the error event may be conditional based on state
variables, but there is nothing conditional about the FSM's transition
once that condition prevails. In this case I think the UI should check
the input values and generate the appropriate event if you really want
the motor to respond that way.
Remember this is not the motor control statechart. It's the statechart
that is using the inputs to determine what signals to the motor control
will be.

If some other external situation also
triggers a reset to the error state, whoever detects that condition
should generate the appropriate event. It isn't up the the FSM to
detect error conditions in the state of the application (e.g., user
input errors); the FSM just responds appropriately when such conditions
prevail by consuming the triggering event.
That's what it's doing.

If one is using DbC
for design, that should be a responsibility of whoever generates the
event. Thus it is a precondition of consuming the event that the data
in the data packet be consistent. IOW, when using DbC any assertions
made about the input data are checking the correctness of the software,
not the consistency of the data.

When the software becomes broken, that's a job for exception handling.
One might still need a [Stop] state for recovery, but getting there is a
job for the exception handler rather than FSM design.


Getting to stop is a function of working software not broken software.
Responding to faults is something the software must do and do correctly.
Think deadman switch or e-stop.

You indicated that going to the Stop state was the result of
inconsistent user input data for the directions and that is the case I
am addressing.
I also indicated you got there from start. And in neither case does it
indicate there is anything wrong with the software.


I don't care how many other ways there may be to get to
the Stop state; I am only interested in the FSM structure around this
path. I submit that such an error should have been detected by the UI
so that it never reaches the FSM.
That's just what's happening here.

Actually a very common technique in embedded systems is a table of
function pointers. One that a client has me maintain (I didn't design
it) uses a list of pointers to define possible transitions for each
state. Each transistion is defined by a pointer to condition function,
a pointer to an action function to be executed if the condition function
returns true and a pointer to the next state if the transistion is taken
(the condition returns true). If the next state is null the state
doesn't change. And what happens? You can probably guess at his point.
The conditions functions actually perform actions in some cases.

That table of function pointers is basically the second form of STT that
I mentioned above. The condition function is just the sort of
indirection overhead one gets into if one supports the /possibility/ of
conditional relationships. If one doesn't use conditional relationships
the table just contains the action pointers. (Of course if one also
might have exit actions, one needs yet another table.)
Note also thst the condition functions map very cleanly to the
conditions I use in the example I've been using. All that's happened is
each conditions have been wrapped up in a function. Of course my
conditions don't perform actions.

I wasn't commenting on the existence of the condition function except to
note it had been used to perform actions. Without that it would have
bee quite a clean implementation even if it ends up scatterd all over
God's half acre. If you don't have the tools to let you draw and
generate code from a statechart though it not a bad approach. I'd
really have liked to not seen actions in the condition functions though,
it makes it a lot harder to follow.

[All commercial full code generators employ the event queue
infrastructure.


Not all of them, the one I use doesn't. It uses that function call. A
lot of state machines I've seen use some variation on that. Some use
tables of function pointers, some use other constructs. There are
actually reasons you might not want tables of constant values in some
embedded systems.

Just out of curiosity, which one is that?
BetterState, WindRiver sells it, although I'm not sure they sell it
separately anymore. They acquired it as part of their purchase of ISI.
ISI bought it from R-Active concepts.

I believe it was developed by Doron Drusinsky as part of his graduate
work so there may well be some papers out there related to it.

The original versions included support for Verilog and VHDL generators,
although I never had the need so I didn't purchase and use them.

I suppose you could convert all the conditional checks by running them
externally and producing event ids for each one. Seems a lot of work
just get get a abstract ID though. The other disadvantage I see with
that is the actual condition is now several steps removed from the
transition it causes.

Not necessarily. Recall my model for Motor. It was actually somewhat
simpler than your model. Its actions could do everything you said were
done in your FSM actions and its transitions enforced the same
sequencing rules that yours did.


No it didn't. It failed on two accounts. It never returned to stop and
it didn't have any forward/reverse assymetry (admittedly a later
clarification). It didn't even have a stop state, just a neutral state.

That's because in your original FSM description Stop didn't do anything
except set DriveRequest to 0, which was what Neutral did.
No, I went back and double checked the revised/clarified version I used
just to be sure. To exit [stop] to [Neutral] direction must be neutral
and throttle must be 0. To exit [neutral] a direction must be selected
but it is not necessary to have the throttle at zero. This enforces the
sequencing that both throttle and direction indicators must be in a
certain state before starting.

When I
changed the state variable and other semantics it was no longer needed.
It did return to Neutral under all the same <substantive> conditions
that you originally specified (or I inferred).
You missed some behaviour.

Now you can argue that your original FSM was designed your way because
of other, unmentioned requirements.
Nope, not my argument. Just an aside mentioning that a complete model
include more ways to get there. Meant to indicate that the direction
indication was acting as a proxy for what would be more possible
transistions in a complete model. You're getting hung up on terminology
rather than duplicating the behaviour.

It also excluded the event generation.

I am not sure what this means. You FSM didn't have any event generation
either; it just selected transitions given an event. Do you mean I
didn't have conditional transitions? If so, that came with changing the
semantics of the state variables and events.
I mean you don't have the full logic available. The full logic includes
the causes of the events as well as their effects. Without that it is
impossible to tell whether the state machine provides the required
behaviour.

It just did it with different
conditions (states), events, and state variables.

I think the condition is only one step removed.


Instead of
call statechart
check condition

You forgot the last step: select a transition. That is equivalent to
generating an event below.
OK so add select a transition to the below as well. Once an event has
been generated you still have to match it with the specific transistion.

you have
check condition
generate event
call statechart

I count an extra step. More if you include the fact you are now check
more conditions than necessary for a given state.

The point is that somebody always detects a condition and announces it
with an event. The FSM always responds to that announcement event by
transitioning to a new state and executing the associated action. That
is about as peer-to-peer as the collaboration can get without bleeding
cohesion between the FSM and the external environment.
Which may make sense (probably does) in another environment, here it
just obscure the logic and adds overhead.

When has a condition check that determines the transition inside the
FSM, one is bleeding cohesion because the FSM is doing part of the job
that the <external> event generator should be doing. Part of the
detection (the trigger event) is outside the FSM and part is inside
(selecting a transition).
Sorry, trigger event? There are no trigger events outside the state
machine unless maybe you are referring to the fact that the state
machine is clocked? I don't see it making a practical difference.

IOW, detecting condition changes is one thing
while responding to them is quite another and I think those two concerns
should be separated.
They are, into condition and action :)

The DbC precondition
for executing any state action exactly matches the postcondition of some
other action (i.e., the one where the event is generated to announce
that its postcondition prevails).


Exactly as in the case of using a simple conditional check.

The problem lies in who owns the condition check (more precisely, who
owns which pieces of a compound condition check), per the point
immediately above.
Methinks we are dealing with differnt issues of scale.

So far I don't see the abstract IDs as any simpler than the conditional
check. Actually I don't see that they are not fundamentally identical
unless you have something running around changing values behind the
state machines back which would be bad design practice IMO.

Why is
if( a < DFG ) {
QueueEvent(queue, QW);
}
if( b == GHJZZ ) {
QueueEvent(queue, QE);
}
StateChart( queue, out);

superior to
StateChart( a, b, out);

There are several reasons. From an aesthetic perspective the FSM
provides /invariant/ constraints on /relative/ sequencing. They should
be invariant relative to the external context.


And how are the constraints I'm using less invariant than events?

They depend upon specific state variable values.
So do the events.

The FSM doesn't care
about the specific values; it only cares that /some/ condition announced
by QW or QE exists.
So the causes of the transitions is obscured by generating events. I
can see this as an advantage in some systems but not in the example I'm
using. If the events are named something convienient like forward I
don't see any difference from checking the direction flags.

The sequencing constraints in the FSM define
intrinsic constraints on when the state actions can be performed
relative to one another without regard to solution context. The
constraints on 'a' and 'b' represent a mapping of intrinsic FSM
sequencing constraints to specific context semantics in the overall
problem solution. That mapping to solution specifics is none of the
FSM's concern.

Suppose there is another object with a method that does something like:

if (x > ABC)
QueueEvent (queue, QW)
if (y != LMNOP)
QueueEvent (queue, QE)
StatrChart (queue, out)
Keep in mind how constrained the system is. These signals have a very
narrow effect. The chance of the signals being used by another context
approaches zero. The chance of the of the same conditions being used in
another context is even smaller. I've never seen either happen.

Now you could have a system with multiple 'throttles' controlling
multiple motors but that just means you have a state chart instance for
each.

OK so why wouldn't conditions based on those same values be well
constrained?

I am talking about data integrity scope here. One can manage things
like thread pausing and whatnot easier if scope is defined by a single
procedure. Similarly, one can focus on the design issues better if
scope of data access is limited to single method scope.
It is so limited. It's limited to the single call of the function doing
the statechart evaluation.

The other thing they can affect is the sequencing of actions within the
FSM. That is essentially what conditional events do; they use context
variables to change the structure of the FSM on the fly.


No more than events do.

Very much more so! If there are no conditional transitions the
structure and sequencing of the FSM for the incoming events is
completely invariant. It depends solely on {event ID, current state}.
No matter how many times that tuple is processed, the path is exactly
the same each time.
The same is true of the conditionals I've used.

However, if there are conditional transitions the structure is
effectively modified. Instead of one possible path for a given event
and current state there are multiple paths that depend upon {event ID,
current state, state var1, state var2, ...}. Thus the structure of the
FSM itself is potentially different each time that {event ID, current
state, ...} tuple is processed.
No more than it would be if you used the (event ID, current state)
approach. Different events or conditions cause different transistions
to occur. That's rather the point isn't it?

All that happens is the conditions get turned into events.

To put it another way, if one drew the
FSM as if only one condition existed, it would have a different
structure than if one drew it for only one of the other conditions.
That last sentence is sort of obvious. If you draw a statechart for one
event only it's different than if you draw it for another event only. I
don't see how that's particularly useful though.

To me that is
kind of like an assigned GOTO in FORTRAN; it opens all sorts of
opportunities for unexpected side affects. IOW when one changes the
data semantics of the state variables one not only needs to worry about
what one computes from the data but which formula one uses to do the
computation.


That's sort of the point. The result depends on the state you are in.
If you don't compute it there you have to have knowledge of which state
the state machine is in externally when you compute it. As far as I'm
concerned that opens the inner workings of the state machine to external
view too much. The during actions express that clearly and directly.

When there are no conditional transitions, one /always/ knows exactly
what path will be taken for a given {event ID, current state} tuple,
regardless of what might be happening in the overall solution.
And with the conditionals one always knows what path will be taken. You
seem to be arguing against something that isn't occurring.

As soon
as one starts to make the path variable, one has an assigned GOTO where
the assignment is done outside the FSM.
The path isn't variable, at least not more so than using events.

If you are in state A and b is true then you take transition C.

if b is true then generate event B
If you are in state A and event B occurs take transistion C

I see no difference in the result of the above approaches.

Those state variables one is using to select transitions are defined and
assigned outside the FSM.
So would the events in your case.

They represent external context. So one is
bleeding that context into the FSM, which makes the FSM more complex.
The events also bleed the same context in.

It also splits up compound conditions between whoever generates the
triggering event and the FSM itself. (Somebody still has to know it is
time to generate an event to the FSM.)
The same will be true in the event case. It is still necessary for the
state machine to be clocked. This clocking BTW comes for free since the
inputs arrive in a synchronous fashion.

That is an issue of separation of concerns. The FSM structure is
inherently static. Modifying transitions dynamically adds another
dimension of complexity to the FSM structure and that is probably not a
good idea.


Who's modifying transistions dynamically?

You are any time you modify the state variable used to select a
conditional transition during the life of the FSM.
What are you talking about? The state machine doesn't modify anything
it uses to make a decision. Sure the inputs will vary on each cycle but
surely with events the events would be expected to change on each call
as well.

One way that is manifested is in the notion of OO announcement messages
(I'm Done) compared to procedural imperative messages (Do This). The
event being generated announces a change in condition /outside/ the FSM.
That is, the event itself is announcing something happening
externally. As it happens that depends upon 'a' and 'b'. But it
announces a compound condition that also includes whatever the caller
did. IOW, the condition being announced is {(a < DFG), caller completed
its part of the solution} OR {(b == GHJZZ), caller completed its part of
the solution}.


Or just as likely both. The state machine then has to discard the
irrelevant events.

I think ignoring events in the STT is a quite different thing than
conditional transitions.
But it does become a question of efficiency. I've become used to having
more than 16K of RAM available but I'm still not inclined to waste it by
providing a queue most of the elements of which are used to buffer
items that will be generated and then immediately thrown away. That's
w/o mentioning the extra time taken.

There is no law that requires one to do
something in response to raising a condition, so it is valid to ignore
certain events when the FSM is in a particular state.

The issue here is choosing a transition path from among alternatives
_when the event cannot be ignored_.
What? Choose via condition or choose via condition transformed in an
event, I see no difference in the end result. I do see the condition
code adding a layer of complexity.

More importantly, it includes a context decision that the IF statements
themselves define. Those IF statements implement problem space rules
and policies to determine exactly What should be announced.


Beg pardon? I think you are envisioning an entirely different kind of
problem than I am. The state machine must be aware of all the inputs
(or events) anything else would be unsafe. The only way anything
external to the state machine could filter the events/data to a subset
would be if it were aware of the state it was in.

The FSM only needs to be aware of events and the relevant input alphabet
for a transition that is processed by the corresponding action. That's
all an FSM does: it responds to events by processing the the input alphabet.
And?

My point here is when you select a transition you are defining a
particular state for the FSM (i.e., the target state for the selected
transition).
Of course.

The precondition for entering that state is a compound
condition composed of:

- the postcondition of the action the generated the trigger event
So an event occurred/a condition was met.

- any data integrity constraints on state variables to be accessed by
the action
??? I think you are envisioning a different problem set.

- the conditions used to select the transition.
That's a repeat of the first line.

IOW, the conditions used to select the transition are necessarily part
of the precondition for entering the target state. If they did not
evaluate TRUE, transitioning to that state would be inappropriate.
The conditions to enter the state must be true or you can't enter the
state. That much does seem obvious.

The primary issue of this whole subdiscussion is whether that
precondition should be evaluated in one place or in two places.
What? I'm evaluating as the check on the transistion. You are
evaluating to generate events. I don't see a difference.

The FSM
only responds to the announcement. If one moves the IF statements into
the FSM itself, one is moving that external context decision into the
FSM. That external context decision probably isn't any of the FSM's
business; it should just respond to the decision's /result/.


?? That external context is the entire reason for the state machine to
exist. Having said that the external context may be abstracted or
idealized. The direction input could be a single multivalued input
rather than a pair of flags as a for instance.

The state variables being tested /are/ the external context. Forward
and Reverse or 'a' and 'b' in your examples have their values assigned
based upon conditions that exist outside the FSM.
Yes and that's the entire reason for the state machine to exist is to
evaluate what state to be in as a result of those values.

They have semantics
that is defined in terms of that external context.

I am arguing that such external context should be evaluated externally
(preferably in one place) and an appropriate event generated to the FSM
based on that evaluation. If one always encapsulates the rules and
policies for detecting state changes that way in a place that logically
understands the context semantics, one never needs conditional events in
the receiver FSMs.
You've just called them events instead and now to unserstand the state
machine you have to have the state chart on one page and the definition
of all the events on another. It'll certainly work but for the context
I'm using it in it does seem pointless complexity.

Finally, when managing complexity it is wise to isolate related rules
and policies via encapsulation. It is highly unlikely that the rules
and policies that determine what event to generate will be logically
related to the rules and policies that the FSM exists to resolve. So if
one moves those rules and policies into the FSM, one is trashing the
cohesion of the FSM.


While there is a lot to encapsulation and isolation it is quite possible
to take it too far. Data and actions that are tightly coupled should
not be separated.

True. That's why one needs a design methodology to draw the lines in
the sand. The OO paradigm draws lines in the sand based on problem
space abstraction while Structured Programming drew them based upon
functional decomposition.

But I would still argue that the rules and policies for detecting state
changes are going to be quite different than those that govern the
response to state changes, regardless of what methodology one uses. B-)
Condition and action are different. Well yes.

The bottom line is that the software will be more maintainable if one
decouples message and method, separates concerns, and encapsulates rules
and policies in a cohesive fashion. Superficially both your examples do
the same thing. But devil is in the details and from the perspective of
maintainability there are potentially huge differences when one gets to
the details.


Actually, encapsulation is a big reason for choosing the form I use in
the example rather than an event queue. All of the logic for
determining the requested drive signal is isolated to the state machine.

And this is a core disagreement. To me conditional transitions
represent lack of cohesion and poor separation of concerns.
I don't think we are going to agree on this. I can see it's utility in
larger problems, especially when a state machine gets reused with
different sources for it's events but that is just not the case here.

We have at least reached the point where we understand during actions.
I hope we can reach the point where we have something similar on the
state machine structure. I expect we will always disagree on
events/conditions.

Robert

--
From the Divided by a Common Language File (Edited to protect the
guilty)
ME - "I'd like to get Price and delivery for connector Part # XXXXX"
Dist./Rep - "$X.XX Lead time 37 days"
ME - "Anything we can do about lead time? 37 days seems a bit high."
Dist./Rep - "that is the lead time given because our stock is live....
we currently have stock."


--
Posted via a free Usenet account from http://www.teranews.com
 
In article <lCWnh.1255$Ul4.124@trnddc05>, H. S. Lahman says...
Responding to Adsett...

We are repeating ourselves, which is a sure sign of talking past each
other. I took one more pass at clarifying my position, but I think we
are close to the point where we need to agree to disagree.
You are quite right. And on that note I'll not reply to your points. I
promise I will further consider your points and over time I may even
accept more of them :) I don't think they are completely invalid BTW.

FWIW I've had a few of the jumping up and down and shouting at the
screen episodes myself during this discussion. :)

I would be surprised if everyone else hadn't tuned out long ago though.

Maybe our paths will cross again. I wish you well

Robert

--
From the Divided by a Common Language File (Edited to protect the
guilty)
ME - "I'd like to get Price and delivery for connector Part # XXXXX"
Dist./Rep - "$X.XX Lead time 37 days"
ME - "Anything we can do about lead time? 37 days seems a bit high."
Dist./Rep - "that is the lead time given because our stock is live....
we currently have stock."


--
Posted via a free Usenet account from http://www.teranews.com
 
Responding to Adsett...

You lubrication vs. cooling example demonstrates that.


Um, it's not vs, They were separate examples.
?? You combined them for one state condition. I was using 'versus' to
argue against that precisely because of the apples/oranges thing.

The incoming signals can indicate forward, reverse, neutral or be
invalid. The throttle can independantly be anywhere in its range. In a
complete example it could also be out of range but I did want a simple
example :) I also don't deal here with finite allowable tme to switch
directions, deadman switches and anti-tiedown logic :)

As a result of these the output could be forward, reverse, neutral or
stop.

My issue is: why can't the incoming signal be changeDirection rather
than an explicit Forward/Reverse couplet?


I suppose they could be but you would then still have to figure out
which direction it had changed to. I suppose you could generate
different events for each possibility but I think we've lost the
advantage at that point.
If one captures current direction in a state variable rather than in an
FSM state, then all one has is a toggle that is triggered by a single
event with no data packet. So I don't see a need for "different events".

Thus in your example one could change the function arguments to
{directionIsToggled, throttleSetting}. Then the function logic checks
directionIsToggled and the currentDirection state variable's value to
decide what to do. The result would be just as deterministic; only the
IF conditions would change.

snip FSM example

OK. AFAICT, this a function takes arguments of {isForward, isReverse,
throttle} and uses them to set the value of DriveRequest and,
optionally, invoke two other functions for ReverseAlarm. To do that it
needs to understand the history of prior invocations, which is
summarized in a value for current state.

If so, then I don't see any "during action". There is only one "event"
and it is always the call to the function. The only thing that changes
are the values in the data packet. That "event" is dispatched to the
appropriate "call to statechart" method for each state based on the
value of current state and the data packet values. Then the value of
DriveRequest is always set on entry to the current state using the rules
and policies that prevail for that state. IOW, this seems to be an
ordinary Moore FSM with only entry actions (i.e., the individual "call
to statechart" method for each state).


OK, seems an odd way to view it to me but I can see the equivalency.
Hmmm. I thought I was just mapping what you provided, so let me expand
on my analysis of the example...

By your description (i.e., the statechart is implemented as a single
function) the function call is the event message to the FSM from the
external world. Since there is only one function call and it always has
the same data packet, there is only one event that triggers all
transitions. That's unusual for practical FSMs but not illegal; one
only /needs/ different events if there are multiple unconditional
transitions out of a state. (In your example multiple exiting
transitions is handled by conditional events.)

In your example, you identified a "call to statechart" whose body did
different things depending on what the state was. I assumed those were
the methods for individual state or transition actions since all the
business rules seemed to be contained in them. Those methods mapped
uniquely to states since you associated each one with a state number.
In addition, there were no other methods doing anything (other than the
transition dispatch in the function itself).

Those methods seem to be the only FSM actions in the example AND they
were explicitly associated with a particular state AND they were called
after a transition had been selected but before the 'current state' was
set. So they had to be executed while entering the state. Consequently
the FSM has to be a simple Moore FSM.

Since DriveRequest is set in the body of those actions rather than in
some other method, I don't see any "during action". That is, Drive
Request can only be set if an FSM event is consumed (i.e., the
statechart function is called) AND it is only set after a <conditional>
transition is selected to a specific state AND the action seems to be a
Moore action. So I don't see any other interpretation.

The only thing I see as unusual in the example is the way that way
transitions were selected. It is done within the statechart function
rather than in a spearate event queue or through a static class STT
lookup table. IOW, you are combining the event queue and STT in the
single function that initially consumes the event.

In addition, the dispatch is based upon the value of 'current state' and
the values of the input alphabet (event data packet). In a true FSM the
input alphabet is irrelevant and the dispatch is based the value of
'current state' and the event ID. That is, conditional transitions are
an overlay to a pure FSM that explicitly employs state variables, which
don't exist for FSAs.

FWIW, with regard to conditional transitions, I am a purist and don't
regard them as true FSMs for two reasons. One is that they aren't
necessary, as my model for Motor demonstrated. In three decades of
mucking with FSMs I've never used one. (That is the main thing I meant
when I said I would do the FSM "differently".) IOW, I see value in
keeping the notation simple even if is occasionally causes the developer
some slight inconvenience.

<aside>
Back in the '80s there was an OO guru who showed up at conferences with
papers proposing enhancements to the OOA/D notations. Invariably these
were special cases of existing notation mechanisms that were tied to
specific problem semantics. His enhancements were elegant and they made
the problem space intent quite clear. But the OOP would be implemented
exactly the same way with or without his enhancements. That is, the
existing, more generic notational elements were just as complete,
precise, and unambiguous in specifying what the application had to do.

To me he was missing the point of having an OOA/D notation. In the end
one is specifying what the application needs to do, so correct
specification is pretty much a given. OTOH, an OOA/D notation deals
with a complex conceptual subject matter so correct OOA/D models aren't
all that easy to construct. It is generally recognized that simplicity
aids communication and has value in managing complexity. Thus one wants
a notation that is simple and easy to understand _in order to get the
specification right_ because one does not want to be distracted by the
complexity the notation itself. So one doesn't want several different
ways of specifying the same thing that can cause confusion.

A classic example was COBOL. COBOL was universally vilified because it
was verbose and yet until the RAD IDEs and infrastructures of the '90s
the vast majority of the world's software was written in COBOL. That
was despite the fact that languages like PL/I and C offered lots of
elegant ways to solve the same basic problems. Why? Because it was
simple. The language was verbose only because of the number of
keystrokes needed to type in its constructs. But the constructs
themselves were quite unambiguous and remarkably simple semantically
compared to languages like C or PL/I. So COBOL allowed the big IT shops
to employ acres of entry level developers while shops using tricky
languages like PL/I and C had to hire experts and there are a lot more
journeyman developers than experts.

[Grace Hopper is still one of my heroes because she got it so close to
right in the 2nd 3GL ever invented. Tough lady, too; she made Admiral
in an era when Navy women were supposed to be secretaries and nurses!]
</aside>

The second reason has to do with the scope of data integrity. When a
state action messes with state variables the scope is well defined as
the method boundary. In the OO paradigm this is further augmented
because methods are self-contained and messages rarely have data packets
since methods are expected to access the data they need synchronously on
an as-needed basis. Under those conditions the method boundary is a
very convenient scope for managing data integrity, especially in
concurrent environments (i.e., providing blocking semaphores, pausing
threads, etc. is <relatively> easy because of the bounded scope). [It
also helps that in stack-based hardware architectures one gets some
scope management "for free".]

However, when selecting the transition to a state depends on state
variable values, one is in another ballpark because accessing those
variables is outside the scope of the target state action. In effect
one needs to manage two different scopes for data integrity while
consuming an event and one of them is not conveniently bounded by the
call stack.

As a translationist I am especially sensitive to this because a full
code generator needs to optimize around this sort of thing. If the
scope of data integrity is not limited to the scope of a single method,
it tends to significantly impede any optimization. I submit that the
same complexity that impedes optimization is also a potential problem
for future maintenance.

[Commercial code generators tend to ignore the problem if they support
conditional transitions in UML Statecharts. IOW, they assume the
developer will make sure the tested state variable is correct in all
circumstances where an event can be consumed. But that just puts the
optimization problem in the developer's lap and adds the resolution of
nonfunctional requirements to the developer's problems.]

I have enjoyed this BTW, hopefully it's not been too much of an
annoyance to you or anyone else.
I'm retired now so I've got time on my hands. B-) In addition, after
many moons in the business I find that I have an oversupply of opinions
that I need to get rid of anyway, so I welcome the opportunity.


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
 

Welcome to EDABoard.com

Sponsor

Back
Top