[Qt-interest] QStateMachine API and design?
K. Frank
kfrank29.c at gmail.com
Thu Nov 4 19:22:06 CET 2010
Hi Steve -
I would make a couple of philosophical comments:
On Thu, Nov 4, 2010 at 8:26 AM, Stephen Kelly <steveire at gmail.com> wrote:
>
> Hi,
>
> After figuring out how to use QStateMachine to do what I want I have some
> questions. I'm sure it's all deliberate, but I can't figure out why some
> things are the way they are.
> ...
First, the features you are asking for could well make sense,
depending on what you are trying to do.
Foreshadowing the comments I make below, in the real world
we often mix programming paradigms, legitimately, and to good
effect.
(Second, I don't know whether the Qt state-machine framework
offers the capabilities you seek, either directly, or with fairly simple
work-arounds.)
Having said that...
> * Why is there no 'current state'? There is a configuration() which gives me
> a set of QStates, but it doesn't tell me which one is the current one. To
> get that I iterate over the set and analyse the parent() until I get the
> 'most extended' state.
One way to understand the motivation for state machines is to think
of them as another paradigm for managing the flow of control in your
program.
In some programs you find that "state" -- stuff that could be represented
by data variables, such as "Is X true?" or "I am waiting for event Y." -- is
encoded instead by the value of the "instruction pointer", e.g., where you
are in some nested set of if-then clauses. When this happens, code gets
difficult to understand and maintain.
To help manage this problem, state machines turn this around and make
the state explicit -- as the value of a state variable, or as the instance of a
polymorphic variable assigned to a state variable, and furthermore the
state now manages the (conceptual) flow of control.
Why do some state-machine frameworks not directly support asking "What
state am I in?", or at least not make that sort of query a central concept?
>From this flow-of-control perspective, for the same reason that most languages
don't support asking "What function am I in?" or "Which line of code is
currently being executed?" Those questions aren't really relevant to the
procedural programming paradigm -- you don't really care what function
you are in; rather, you care what code is executed when you're in that
function.
Similarly, in the state-machine paradigm, you don't really care what state
you're in. Instead you care what transitions you make in response to
incoming events, and what actions these events trigger.
(Now, when I'm developing a procedural program, I often add print statements
for logging and debugging purposes: Print "Entering function XYZ." Print
"Doing stuff." Print "Exiting function XYZ." Yes, and truth be told, I often
add similar print statements to my state-machine programs: Print "Entering
state ABC." I usually add them to the entry actions. But this kind of
logging is layered on top of, and is separate from the core logic of the
underlying programming paradigm.)
> * Why is there no notification when the 'current state' is changed?
Again, to continue with the comparison with procedural programming,
for the same reason that no notification is issued when a function is
called or returns.
> My usecase is to create a state machine and expose it to QML so that I can
> change the ui state on change of the application state. Approximately:
> ...
>From the purist's perspective, the purpose of a state machine is not merely
to store state that some external entity monitors and responds to, but
rather to manage the code that is executed in response to incoming events.
So you might consider elevating your state machine to a loftier role,
and let it directly manage the dynamics of your program, rather than
restricting it storing and updating the value of a state variable.
So suppose you have a state machine, "machine," and a button-widget,
"widget."
Plan A:
machine::state1::onEntry() {
widget.notifyStateChanged();
}
widget::onNotifyStateChanged() {
stateValue = machine.getState();
if (if stateValue == state1) { // <-- if-then code...
setButtonColor (red);
}
else if (stateValue == state2) ...
else ...
}
Instead you can replace plan A with
PlanB:
machine::state1::onEntry() {
widget.setButtonColor (red);
}
I think of state machines as objects with dynamics, in a sense as
control structures, rather than value objects, i.e. objects that store
the value of a state variable. Taking this to its logical conclusion,
state machines should be elevated to a more central, controlling
role.
And if they are, there is no need for them to offer query-state
functionality, nor state-changed notifications.
> All the best,
>
> Steve.
Good luck.
K. Frank
More information about the Qt-interest-old
mailing list