
More State Machine Love: From Reflection to Statecharts - weinzierl
http://raganwald.com/2018/03/03/reflections.html
======
codetrotter
I recently built a state machine for a game I am working on. My state machine
is inspired by reading
[https://statecharts.github.io/](https://statecharts.github.io/) and also by
some of the dispatch stuff from SICP though it had been a while since I read
SICP.

The way I wrote my code is I model the state machine and the states as
separate objects and I model the transitions between states as events with
messages that the states inform the state machine of and then the state
machine looks at what is the current state and what is the current event and
it looks at what state if any it should transition to as a result of this.

Here is the class for my state machine object: [https://github.com/ctsrc/ITR-
LotPT/blob/master/src/statechar...](https://github.com/ctsrc/ITR-
LotPT/blob/master/src/statechart.js)

And here is where I create states and register said states and their
transitions with an instance of my state machine:
[https://github.com/ctsrc/ITR-
LotPT/blob/master/src/main.js](https://github.com/ctsrc/ITR-
LotPT/blob/master/src/main.js)

Prior to reading about statecharts my state machines used to be messy and hard
to reason about. The one I mentioned above feels very clean and I am very
happy with it.

As you can see this state machine I use for transitioning from resource
loading to main menu and then to the main game, as well as going between the
in-game and paused states. For the main game itself I do not use a separate
state machine because currently I feel that if I added that stuff there I
would be adding overhead without much benefit. The game is still in an early
stage and far from finished. The game is in fact not even playable yet. But
like I said I feel good about that state machine of mine.

------
V-2
Interesting in and of itself, and yes I'm familiar with the design pattern,
but with so much code to accomplish the simplest of things, Spolsky's
"architecture astronauts"* spring to my mind straight away. Perhaps it's
JavaScript that's not the best choice of a language here?

____

* [https://www.joelonsoftware.com/2001/04/21/dont-let-architect...](https://www.joelonsoftware.com/2001/04/21/dont-let-architecture-astronauts-scare-you/)

~~~
deckard1
That's a great article that always deserves a read once or twice a year.

> Your typical architecture astronaut will take a fact like “Napster is a
> peer-to-peer service for downloading music” and ignore everything but the
> architecture, thinking it’s interesting because it’s peer to peer,
> completely missing the point that it’s interesting because you can type the
> name of a song and listen to it right away.

This sentence so succinctly summarizes the current "blockchain" craze that
it's hard to believe he wrote it in 2001.

------
sramam
I'm surprised that `javascript-state-machine`[1] hasn't come up yet as a
suggestion. A simple implementation of the bank-account example [2] shows why
the pattern is interesting when the implementation can be declarative.

I haven't tried building a nested/hierarchical state-machine with it - mostly
because I have been able to decompose my problems into units that didn't need
them, but also because hierarchical state machines always give me a head-ache
larger than deadline.

[1] [https://github.com/jakesgordon/javascript-state-
machine](https://github.com/jakesgordon/javascript-state-machine) [2]
[https://gist.github.com/sramam/fba55f5325a8c398870292e1f3cad...](https://gist.github.com/sramam/fba55f5325a8c398870292e1f3cada05)

~~~
chris_st
Indeed... or the Go library fsm[1] based on javascript-state-machine. I
thought I'd use them both in a game I'm building, but I'm leaning towards the
idea that the UI state is just the state that's already in the server's model.

I'm happy that the ability to generate GraphViz drawings has already helped me
find a bug, at design time!

[1] [https://github.com/looplab/fsm](https://github.com/looplab/fsm)

------
michaelsbradley
An implementation of statecharts in Python, under active development:

[https://github.com/aleph2c/miros/](https://github.com/aleph2c/miros/)

[https://aleph2c.github.io/miros/introduction.html](https://aleph2c.github.io/miros/introduction.html)

------
skybrian
This whole idea of having methods appear and disappear depending on the state
seems error-prone: the caller needs to check whether the method exists before
calling it, and nothing enforces this so you'll get runtime errors unless
you're very careful.

In a language like Elm, you'd pattern-match on the current state every time.
Is there a better way?

~~~
sghiassy
I can’t speak to this particular implementation but events in a ststaechart
are supposed to bubble up

That said, a withdrawFunds action shouldn’t be available if the user is in the
loggedOut branch of the statechart

~~~
braythwayt
As it happens, the "chain of prototype" implementation definitely ensures that
method handlers "bubble up," for example the .close method bubbles up.

------
platz
great comments on statecharts previously here
[https://news.ycombinator.com/item?id=15835005](https://news.ycombinator.com/item?id=15835005)

the top few comments i find compellingly skeptical.

[https://news.ycombinator.com/item?id=15835482](https://news.ycombinator.com/item?id=15835482)

[https://news.ycombinator.com/item?id=15835666](https://news.ycombinator.com/item?id=15835666)

~~~
monocasa
The first comment seems to be confusing flow charts with state charts.

The second is addressed with hierarchical state machines.

------
drewfish
In the article the author states:

    
    
      From this, we get that accounts should certainly behave like state machines.
      And from that, it’s reasonable that other pieces of code ought to be able to
      dynamically inspect an account’s current state, as well as its complete graph
      of states and transitions. That’s as much a part of its public interface as
      any particular method.
    

I disagree with this a bit. I think that the state transitions are _not_ part
of the public interface -- they're an implementation detail of the SM. The
public interface of a SM are its states and the events it responds too. It's
up to the SM to decide when to do the transitions. (The _author_ of the SM
would be very interested in it's transition graph/conditions of course.)

For example, reviewing a bunch of the javascript SM libraries I see a few have
the SM define a "transition table". This works for simple SM but makes it
difficult to _conditionally_ transition. Perhaps we want our bank account SM
to automatically transition to the "hold" state if the balance goes below
zero. With a fixed (i.e. as configuration) transition table we can't do this
(or we have to fight against the SM library, or the SM library has to be more
complicated).

I guess I'm fairly influenced by this book: [https://www.amazon.com/Practical-
UML-Statecharts-Event-Drive...](https://www.amazon.com/Practical-UML-
Statecharts-Event-Driven-Programming/dp/0750687061) I found that approach
worked very well when I used it to implement a fairly sophisticated UI on an
embedded device. It was easy to rationalize about, easy to read in the code,
and easy to maintain (add/move states). Seems like something similar in
javascript would be nice, except doing things in a javascript way.

~~~
braythwayt
Author here.

Conditional transitions, before- and after- actions, state entry
conditions/validations, ... There are all sorts of places to go that have been
proven fertile for developing robust software.

But you know... In one essay (two if you count its predecessor)... You have to
draw the line somewhere. The goal is not to present a unified theory of
modelling domain objects with state, nor is it to introduce some code that
should be copied and pasted into a production pull request.

The simple goal is to provoke a conversation.

And if the outcome of that conversation for some people is, "We need
conditional transitions, so the exact thing articulated in the essay is
NoDamnGoodForUs," then I am actually quite satisfied that I've done my job as
a blogger.

And if I can address your specific point--which I hope you understand that I
agree with, even if it disagrees with that one paragraph--there are multiple
approaches, and I think that if we really were modelling bank accounts as
domain object with .deposit or .withdraw methods, we could do just as you
suggest and bake a conditional transition to a Held state.

But we could also ask if the bank account is responsible for making that
decision? In some architectures, we might say that this is burdening it with
too much responsibility. I actually mulled this over with the following use
case, which I decided to cut from the essay:

Consider a "suspicious deposit," or maybe a "suspicious transaction pattern,"
like a series of deposits and immediate withdrawals. PayPal is notorious for
freezing accounts that violate some set of hidden rules.

Should the .deposit and .withdraw methods know about this and sometimes
transition to "held?" One could argue this is not the account's
responsibility, especially if some aspects of what makes a transaction
suspicious involve things outside of the balance, like how long the customer
has been with the institution.

Of course, there could be a line of code that calls a "Transaction Evaluator"
thingummy from within the .deposit and .withdraw methods, or even a .validate
method that always checks for this kind of thing after any action.

Or... Maybe this is a lot more like an MVC architecture, and the
responsibility for checking the transaction falls to the controller, not the
account model. So the controller calls .deposit or .withdraw, and the
controller checks for suspicious transactions (or for negative balances), and
the controller calls .placeHold on the account if necessary (and possibly on
ALL accounts for the customer).

I'm not suggesting that this is superior to your suggestion, but it was
something I thought about, and in some application architectures, I think what
I just described is the way to do it. In others, what you described is the way
to do it.

JM2C. Thanks for your comment.

~~~
drewfish
Good points, I pretty much agree with everything you said. "NoDamnGoodForUs"
is a little strong, more like "AlmostButThisOneUseCaseNeedsALittleMore" :)

Interestingly, that embedded device I made wound up being MVC without
explicitly intending so -- the statecharts were the controllers. The only
conditional transitions had to do with code reuse, where a single
implementation lead to slightly different transitions depending on how it was
configured.

------
gregwebs
I created a simplified javascript statechart implementation several years ago,
which I used to describe client-side application state:
[https://github.com/gregwebs/StateTree](https://github.com/gregwebs/StateTree)

This approach worked quite well for me at the time and still seems to have
more clarity for high-level state management than the modern redux approach.

------
sghiassy
Statecharts are a great data structure for front end applications. Especially
when there’s complicated boot up a sync logic for an app

------
solidsnack9000
Web development might be very different -- both more organized and
understandable, and less error prone -- if state machines had been adopted
more widely than the active record pattern.

State machines are a natural fit for audit logging and replay, both issues
that come up whenever your "models" go into production and customers report
errors.

------
clumsysmurf
The article mentions SCXML, and when I search for java libraries that
implement this, the first one that comes up is Apache Commons SCXML - but the
project seems dead: The last stable release 0.9 was in 2008. Are there any
other viable Java implementations that work on Android?

~~~
netghost
Sometimes inactive just means complete. I think SCXML was specified a while
ago, I can't vouch for any particular library, but it's possible the library
does what it set out to do.

------
agumonkey
What's the relationship between carefully separated states and legal
transition and linear types ?

