
How I Learned to Stop Worrying and Love the State Machine - gregorymichael
http://raganwald.com/2018/02/23/forde.html
======
sktrdie
I've been studying state machines and specifically statecharts (which are
essentially state-machines with hierarchy) for a while now. Here's a great
resource to learn more
[https://statecharts.github.io/](https://statecharts.github.io/)

I absolutely fell in love with them and haven't looked back ever since I
learned more about how they work. As the author explains in this post we're
implicitly writing state-machines all the times in the form of code. The idea
of making them explicit, rather than implicit, helps us visualize the behavior
which would've otherwise been hidden in code.

I'd highly suggest to also read this paper by David Harel, the creator of
statecharts, On Visual Formalisms:
[http://www.wisdom.weizmann.ac.il/~harel/SCANNED.PAPERS/Visua...](http://www.wisdom.weizmann.ac.il/~harel/SCANNED.PAPERS/VisualFormalisms.pdf)

If you're a frontend developer checkout my post on the subject related to
React and Redux specifically: [https://medium.freecodecamp.org/how-to-model-
the-behavior-of...](https://medium.freecodecamp.org/how-to-model-the-behavior-
of-redux-apps-using-statecharts-5e342aad8f66)

~~~
nrclark
Is there much in the way of FOSS statechart implementations? It's been a while
since I looked into the ecosystem.

I remember that the canonical one was always the Quantum framework, but I
never wanted to deal with the licensing aspect of it.

~~~
davidkpiano
Hey! I'm the creator of xstate:
[https://github.com/davidkpiano/xstate](https://github.com/davidkpiano/xstate)
\- a pure, functional, declarative implementation of statecharts in
TypeScript. It has zero dependencies, is frameworkless, and fast (O(n) state
and transition look-up time for most cases).

I have some important updates to announce at JSConf Iceland, including the
ability to translate to/from SCXML, and an improved visualizer.

Let me know what you think!

~~~
nrclark
I think that looks awesome! Makes me wish I was a JS programmer so I could try
it out :)

------
hprotagonist
Eric Lippert's "Wizards and Warriors" blog posts seem appropriate here,
especially as an example of how tracking state and OO can clash pretty badly.

 _A common problem I see in object-oriented design is:

A wizard is a kind of player.

A warrior is a kind of player.

A staff is a kind of weapon.

A sword is a kind of weapon.

A player has a weapon.

But before we get into the details, I just want to point out that I am not
really talking about anything specific to the fantasy RPG genre here.
Everything in this series applies equally well to Papers and Paychecks, but
wizards and warriors are more fun to write about, so there you go.

OK, great, we have five bullet points so let’s write some classes without
thinking about it! What could possibly go wrong?_

[https://ericlippert.com/2015/04/27/wizards-and-warriors-
part...](https://ericlippert.com/2015/04/27/wizards-and-warriors-part-one/)

[https://ericlippert.com/2015/04/30/wizards-and-warriors-
part...](https://ericlippert.com/2015/04/30/wizards-and-warriors-part-two/)

[https://ericlippert.com/2015/05/04/wizards-and-warriors-
part...](https://ericlippert.com/2015/05/04/wizards-and-warriors-part-three/)

[https://ericlippert.com/2015/05/07/wizards-and-warriors-
part...](https://ericlippert.com/2015/05/07/wizards-and-warriors-part-four/)

[https://ericlippert.com/2015/05/11/wizards-and-warriors-
part...](https://ericlippert.com/2015/05/11/wizards-and-warriors-part-five/)

~~~
badsectoracula
The first four articles are interesting and i was following along, but i am
not buying the last solution - it is way too complicated and over-engineered.
It is telling that unlike the other four articles, the last one has no
implementation code.

What i would do is simply have Item (base for Weapon, Potion, etc) have a
"IsUsableBy(Player p)" which returns true in the default implementation (which
would be the case for the majority of items) and the objects that have special
considerations check the player class themselves.

Similarly an Animal (or Entity or Organism or whatever) class would have a
"OnDamage(Animal source, int damage)" that by default calls -say-
"ApplyDamage(int damage)", but special animals - like the werewolves - may
want to filter the result so that the damage is doubled when they are on holy
ground or when the class of source is Paladin.

Also the IsUsableBy and OnDamage functions could check against Item objects in
an inventory (e.g. Item could also provide a "FilterDamage" and "VetoUsageOf"
so that an HolyCross can multiply all damage from Undead enemies by 0.25 but
veto using any UnholyItem based class - truth be told here, you probably need
a tag system for some of that stuff instead of relying on classes alone) and
on an active Effect list (would also be able to do the same sort of vetoing
and filtering and the Animal class could also provide a HasEffect method for
use by the other classes to make decisions about - e.g. a PaperDoll might
refuse to talk to you if you have the OnFireEffect :-P).

To me that sort of setup feels more natural and intuitive than the user-
command-state-rule stuff mentioned in the article. You can't really generalize
it in a way that applies to other things (e.g. a MagicSpell would need its own
set of functions and such) but i believe that there is a thing as too much
generalization.

(note that the above are when talking about the common Java/C++/C#/etc like
OOP languages, in something like C i'd go with a more data and/or script
driven approach...)

~~~
psyc
I agree with you up to a point, and that point is when the game becomes
"large" in the number of rules and entity varieties. Eric is approaching this
very much like a compiler developer. We always have the option of 'lofting'
concepts out of the code and into types. E.g. we usually start by writing:

    
    
      int a = 1;
      int b = 1;
      int c = a + b;
    

And we have the option of writing, alternatively:

    
    
      class Integer { ... }
      class Operation { ... }
      class Expression { ... }
    

Or something 'meta' like that. The upside is that it's flexible, powerful,
expressive to turn code into data. The downside is that it's slower, and
there's a whole extra system to maintain.

However, in my experience as a game developer, past a certain large size,
pretty much all systems seem to want to converge to Lippert's solution. You
want to be able to put the entity data _and_ the rules into tables, and not
have to edit code to change the game rules. For small games, not worth it. But
for large games, and also for game _engines_ that aspire to be generic, it
makes everything a lot easier.

~~~
badsectoracula
I wanted to stick with the language side this that is what the original
article was about. But yes, in large games you wouldn't do all that stuff in
C#/C++/etc, you'll most likely use a data driven approach. However this can
still be put at the gameplay side of the engine to provide the base. For
example if you look at the mod tools for RPG engines like Aurora, Creation Kit
and REDEngine you'll see that they have inherent knowledge about base item
types like armor, monster, etc, but they rely on data for the specific items
(and scripts for the exceptional behavior). The easiest to see that is with
the Creation Kit based games like Skyrim since it gives you a nice GUI to
create/edit each different item type.

------
rdtsc
Erlang, which traditionally deals with concurrency and parsing protocol has
had a built-in standard FSM module for a long while:

[http://learnyousomeerlang.com/finite-state-
machines](http://learnyousomeerlang.com/finite-state-machines)

It even got a recent re-write and the new one is called gen_statem:
[http://erlang.org/doc/man/gen_statem.html](http://erlang.org/doc/man/gen_statem.html)

This new version is already is used to handle some of the TLS and SSH stuff
from what I've heard. Here is TLS connection code:
[https://github.com/erlang/otp/blob/11cd0f1d000be5849bba2466b...](https://github.com/erlang/otp/blob/11cd0f1d000be5849bba2466b3b54daa7727af22/lib/ssl/src/tls_connection.erl)

I've done them in C and Python before as well. In C I the like the table +
function pointers approach when possible. Here is an example:
[https://stackoverflow.com/questions/133214/is-there-a-
typica...](https://stackoverflow.com/questions/133214/is-there-a-typical-
state-machine-implementation-pattern?answertab=active#tab-top)

~~~
tonyarkles
Even without the framework, Erlang/Elixir processes very naturally lend
themselves to statemachine-like behaviour. Unless you're doing something
really weird, the messaging behaviour is basically:

    
    
        new state = old state + message

~~~
rdtsc
Indeed. In Erlang I had never actually used any of the FSM modules in practice
because in my case a simple gen_server works just as well.

------
richdougherty
Here's a tip for state machines. If you've got a transition that takes some
time then you often actually need another state to represent the state that
the system is in during the "transition".

This is usually modeled better on backend systems (a state while waiting for a
network response to arrive) but is often modeled poorly in front-end systems
(a state while waiting for an animation to finish).

~~~
HeyLaughingBoy
This is something I had to deal with pretty recently. The sequence I needed to
model was:

Operator pushes Start

Turn motor on

Motion triggers switch to ON state

Motion triggers switch to OFF state

Turn motor off

Machine changes state to RUNNING

The time between pushing Start and RUNNING is only a couple seconds, but
there's a chance that something could jam, the switches could fail, or
something I have no knowledge of could go wrong. Question becomes, do I now
need an intermediate "In Motion" state for the six or so cases where this
happens?

In the end, I decided no, because there was no other transition out of that
state than the expected behaviors, so modeling the intermediate state didn't
offer me any benefit[1]. Failure to get to OFF state within a certain time
puts the system into a global error condition that required manual
intervention to fix.

I don't have a real comment here :-) other than to back up your point that
modeling isn't as obvious as it first appears to be.

[1] I would have created this intermediate state if this was a complex
controller that was likely to have new rules added later. However, knowing it
was a simple one-off, I'd just be giving myself extra work for no benefit if I
did it now.

~~~
lfowles
I prefer having nominal intermediate states just for debugging purposes. "What
am I doing now? Does being in START imply it's already started the process?
Does being in RUNNING imply the process was completed successfully?" vs "What
am I doing now? In motion!"

In the example given, I'd probably stick to a single intermediate state and
let the language work as my implicit state machine for the internals.

Depends a lot on the boilerplate required to insert states though, my
preferences owe a lot to the HFSM implementations I've used in the past.

------
craigkerstiens
Love seeing more about this. It's a great design pattern for many systems.

We used this approach back at Heroku to power Heroku Postgres and follow the
same to power our database as a service at Citus as well
([https://www.citusdata.com/blog/2016/08/12/state-machines-
to-...](https://www.citusdata.com/blog/2016/08/12/state-machines-to-run-
databases/)). The approach has scaled extremely well due to us following a few
key principles (most importantly that we don't change the state of a running
database, rather we failover to some new one with the new state).

------
jonasvp
I distinctly remember the first time I looked at a overly long and complicated
model class and thought: "OMG, this is a state machine!" \- a shortish
refactor later and it was _much_ simpler to read and debug.

However, now I'm at a loss on how to teach the junior programmers at my
company how to recognize which patterns scream "turn me into a state machine!"
Several booleans triggering certain code paths in several methods is a pretty
sure sign. Are there more?

~~~
bsder
The word "protocol" is a big red flag that you should be using a state
machine.

The words "event loop" probably mean you need a state machine.

If "time" is an input variable, you probably have a state machine.

~~~
criddell
I've also found the presence of a _mode_ variable a good indicator that a FSM
should at least be considered.

------
zengid
I remember reading about a language from Microsoft called P that compiles to
state machines in C. Its for complex and asynchronous state changes, like
programming a protocol for an automated drone.

[https://www.microsoft.com/en-
us/research/blog/p-programming-...](https://www.microsoft.com/en-
us/research/blog/p-programming-language-asynchrony/)

~~~
JoachimS
I'm slightly surprised that nobody (as far as I've seen) have mentioned SDL:
[https://en.wikipedia.org/wiki/Specification_and_Description_...](https://en.wikipedia.org/wiki/Specification_and_Description_Language)

SDL is widely used in telecom and datacom systems to develop the control
plane. Most tools are of the draw your code-type, which ends up being a
unmanagable mess in direct contrast to what management thinks. But the tools
will generate state machines that pass messages between eachother and to
controlling interfaces based on states an inputs.

The point being made for SDL is that you can easily simulate the whole system
and watch/test that the control plane will work as intended before the HW has
been built.

------
epx
Coincidence, I've written something about it two weeks ago (in Portuguese,
unfortunately:
[https://epxx.co/logbook/entries/sm.html](https://epxx.co/logbook/entries/sm.html)).
About Petri Nets as well. It is difficult to understand why so many junior
programmers use a dozen boolean state variables instead of a state machine,
given that they learn it in CS or similar courses. My guess is they are taught
in an overly scientific fashion, so they go to the same dusty corner where so
many other CS topics that are never used in practice lie already.

~~~
stcredzero
_go to the same dusty corner where so many other CS topics that are never used
in practice lie already_

I've been meaning to write a letter to the CS department of one UC school:
What the hell are they teaching in CS nowadays? If presented with a situation
where the user can create circular references, there's one UC school that
produces graduates with high 3.8+ GPAs, virtually none of whom I've
interviewed can give you an implementable description of how to detect
circular references. As a general pattern, they also tend to say silly things,
like that a null pointer member of a structure uses up no data. I can go on
and on. It seems to me they are being taught by TAs who would also flub such
points in an interview.

~~~
hateduser2
How is being able to detect circular references a useful skill?

~~~
stcredzero
_> How is being able to detect circular references a useful skill?_

For all kinds of systems, where there are references input by users as data,
one needs to be able to contend with this. Systems which crawl webpages have
to contend with this. Parser-transformation systems need to detect these. Such
detection could be useful in memory management. It's not just the ability to
detect a circular reference. It's the ability to contend with problems of that
type.

Furthermore, two of those UC system CS grads had eerily similar responses,
consisting of, "Oh, is that a graph algorithm?" plus a literal handwave. Is
there some pool of TAs somewhere that has that attitude towards graph
algorithms?

~~~
westoncb
Hmm, this seems like a kind of understandable attitude if I'm reading it
correctly. Hearing that it's a (standard) graph algorithm means it's a solved
problem so you don't need to worry about it: pick up a text book or Google and
compare the available options—easy.

------
madhadron
This reminds me of my old mentor Julian Noble's Forth code that makes state
machine transition tables valid code:
[http://galileo.phys.virginia.edu/classes/551.jvn.fall01/fsm....](http://galileo.phys.virginia.edu/classes/551.jvn.fall01/fsm.html)

------
jstimpfle
This is another important argument _against_ class-based object oriented
programming. There are only very few "objects" so small as the ones
conventionally created in OOP. If money is withdrawn from a bank account, it's
going to be put somewhere else. Withdrawing money from an account is not an
operation on an account, but on a larger system that _includes_ the account.
So making an "account" class with a "widthdraw" method is a bad idea.

Very often a program has only one or very few meaningful state machines, and
pretty much always they are "global", i.e. there is only one of its kind in a
process.

Just use global state, it has the best possible syntax for OOP :-)

~~~
dnomad
In the real world nobody would ever create an Account class with a 'withdraw'
method. Withdrawals are always first class entities that unique IDs and states
of their own. Every Withdrawal is itself a request with a lifecycle that, only
if completed successfully, results in an event and changes to the system.

This example is very reductive. In a rich and constantly changing domain like
banking using a state machine to model core entities like an Account almost
always ends in disaster. It simply doesn't work because businesses are complex
and ever-changing. Virtually every time I've seen a 'STATE' property in a core
entity, especially if it's a public property, it has evolved over time to
become a horrendous thing that nobody really understands but it is now
integrated throughout so many codebases that people have no choice but to
continue supporting it. Ugh.

The real point here is that state machines are mathematical, highly specified
constructs. They do not change well. If you are working on a protocol that can
be specified precisely, sure use a state machine. If you're working on a
business entity think long and hard about whether these requirements are truly
fundamental and will never change. And if you really do think you have a state
machine at least don't make it public.

~~~
cma
What you often see instead of a simple state enum is 5 boolean getters and a
bunch of logic that has things like "panic if this bool is true and this one
isn't, that should never happen." Whereas with a simple state enum
representing the same thing you can often just make the invalid combinations
have no representation at all.

------
nickpsecurity
And once you're confortable with FSM's, you might try Abstract, State Machines
(ASM's) for formally specifying or verifying software:

[http://www.di.unipi.it/~boerger/Papers/Methodology/BcsFacs07...](http://www.di.unipi.it/~boerger/Papers/Methodology/BcsFacs07.pdf)

Microsoft even had a gool, AsmL, for this method. TLA's PlusCal specs look
similar to some Ive seen in ASM's, too.

~~~
metalliqaz
Microsoft has the best gools.

~~~
mcguire
Microsoft has the only gools.

------
notduncansmith
Shameless plug: I’ve been working on some open-ended state-machine-like
constructs in Clojure and JavaScript -
[https://github.com/notduncansmith/factfold](https://github.com/notduncansmith/factfold)

The idea is to capture the useful properties of state machines without being
constrained to enumerable states.

I’m currently working on a program to edit these machines visually.

------
jonahx
Fun fact: The J language implements general finite state machines as a
_language primitive_ \-- `;:`

[http://www.jsoftware.com/help/dictionary/d332.htm](http://www.jsoftware.com/help/dictionary/d332.htm)

------
manmal
State machines are my #1 „magic trick“ for writing reliable code in Swift. In
Swift you can attach values to enum cases, so you have implicit data stored
with each state. UI states are very well suited for this (Eg .loading,
.success(value), .error(error, cached)), or API request states (.initial,
.fetching(isRetrying), .success(value), .error(error)). Each can cycle through
each state, and each state translation can be handled and animated or ignored.
I cannot stress enough how much this improves the resulting code. Most bugs I
get now are almost „intended“ as I chose a certain behaviour for a certain
state, but that decision was wrong (rather than the code flying in my face
unexpectedly).

------
skybrian
I find the original example to be much clearer. If you want to know about all
the valid transitions from the 'held' state, search for all usages of 'held'.
Adding complicated dispatching doesn't help readability.

This seems a lot like the expression problem [1]. There are no perfect
solutions. A problem can be split along multiple dimensions, but not all at
once, or at least not as code saved in a text file.

Whether you split the problem first by method or by state, you will have code
that's located far away from closely related code.

[1]
[https://en.wikipedia.org/wiki/Expression_problem](https://en.wikipedia.org/wiki/Expression_problem)

------
michelpp
State machines also make excellent database constraints. Trigger based
enforcement removes the need to implement machines in application languages
and prevents bad code from inserting bogus states. This only matters if you're
storing state data in a DB. For example I wrote a simple trigger based fsm
extension for postgres:

[https://github.com/michelp/sqlfsm](https://github.com/michelp/sqlfsm)

------
3pt14159
Eh. State machines have their place, and I find them especially helpful for
simultaneous code of all kinds, but for run of the mill business logic I find
they just get in the way of the code. My rough rule of thumb is this:

1\. Can simultaneous actions hurt here?

2\. Would a database transactions work instead?

Iff the answer is "yes" to the first and "no" to the second then consider
state machines. Make sure the answer to #1 is really "yes" though. For
example, things like animations consider libraries like Ember Concurrency
which give you fine grain control over queuing and restarting things without
the muck of a bunch of states and transitions.

------
pron
It's unfortunate that the article (and Wikipedia, too), use "state machine" to
refer to a _finite_ state machines. In program semantics and formal
verification, the term state machine is a common term of art, but it refers to
either a finite- _or an infinite-_ state machine, with infinite being the
presumed default unless otherwise stated. If people come to associate the
concept of a state machine with the useful but more limited narrowly
applicable concept of a _finite_ state machine, they may miss out on this
important and general concept.

In program semantics and formal verification, a state machine is a
mathematical mechanism for describing an often nondeterministic discrete
(software or hardware) system as a mathematical relation, →, on states, where
if `s → t` (i.e., the pair <s,t> is in the relation), then a transition from
state `s` to state `t` is possible. For example, both Turing machines and the
lambda calculus are often naturally described as state machines. A _finite_
state machine is just a state machine with a finite number of states.

~~~
braythwayt
There are more generalized concepts of great interest, including infinite
state machines and (as mentioned elsewhere in this discussion) hierarchal
state machines.

However... A blog post with the stated aim of alerting programmers to the
opportunities for refactoring a convoluted domain model into something with
more structure has to start somewhere, and leave something out.

The great thing about discussions like this is that more experienced
programmers such as yourself can chime in with exactly this kind of
observation.

I invite you to post a link or two for others to read. I'm sure the community
will appreciate it.

~~~
lou1306
May I chime in? _A gentle introduction to process algebras_ [^1] shows some
examples of how you can represent programs as (possibly infinite) state
machines. Essentially you define some operators to compose smaller programs
(aka. _processes_ ) into larger ones, hence the name "process algebra". These
definitions allow you to "see" your process as a generalization of a state
machine known as a labeled transition system [^2]. And then you can exploit
this representation to verify properties about the process. Lots of fun!

[^1]:
[https://pdfs.semanticscholar.org/12d9/eae1638729aeb237b5be44...](https://pdfs.semanticscholar.org/12d9/eae1638729aeb237b5be445ee91ecdd3c5d7.pdf)

[^2]: These rules are called an _operational semantics_. There are other ways
of giving semantics to a formal system: for instance, _denotational_ semantics
exploit recursive mathematical definitions. Each way has its pros and cons.

~~~
pron
State machines (that contain both labeled and unlabeled transition systems)
may indeed serve as operational semantics of some formalisms, but they can be
denotational semantics of others, or even studied completely separately from
any programming formalism.

Not only process algebras, but even the lambda calculus is naturally expressed
as a state machine, where the states represent the expression, and transitions
represent possible reductions (lambda calculus is nondeterministic).

------
brentjanderson
The sample code is fine for JavaScript, but it begs to be written using
pattern matching, like that in Elixir/Erlang. If you have the current state
and an event to apply to that state (similar to Redux), you can pattern match
on pieces of the current state and the event to apply to that state. Your
event handler could look like:

``` def handle(%{state: "open", balance: balance},%Deposit{amount: amount}) do
{:ok, %{state: "open", balance: (balance + amount)}} end

def handle(%{state: "closed"}, %Deposit{}) do {:error, "invalid action:
account closed"} end

```

Every state/event pairing is explicitly defined as a variation of the `handle`
method. There are countless ways to build a state machine like this, but the
basic pattern matching primitive seems to simplify this a lot.

An extension to javascript to support this has been proposed, I'm hopeful that
it gets considered seriously: [https://github.com/tc39/proposal-pattern-
matching](https://github.com/tc39/proposal-pattern-matching)

------
wyldfire
The state machine is a powerful/clear metaphor to align your design. IMO
hierarchical state machines (aka Harel statecharts) are a superior variant
that makes behavior yet clearer and easier to design.

~~~
stcredzero
_Harel statecharts_

I wonder how those map to "Behavior Trees" in game development?

~~~
meheleventyone
A behaviour tree is sort of a hierarchical state machine but one in which the
states are not explicit. They fall out of how you arrange the nodes in the
tree.

Actual hierarchical state machines are pretty common for driving a variety of
things. Probably most commonly animation but also driving game state.

~~~
stcredzero
_Actual hierarchical state machines are pretty common for driving a variety of
things._

My understanding of hierarchical state machines, is that they're equivalent to
Context Free Languages in terms of computational power.

------
kazinator
When state machines are finite, and are well-formalized, they are fairly easy
to understand and debug.

State machines descriptions can lie. For instance, suppose that the
implementation of a state machine grows hair that is not folded back into the
specification. For instance, originally, the outputs of state transitions were
just pure outputs. Now they are secretly fed back into the machine and give
rise to additional states.

Or, originally, the state machine just consumed input events and changed
state. Now, without it being clear in the diagrams and documentation, the
machine can push back any number of events into the event stream to process
again, including rearranged and edited versions of the events. This is just
modeled as an "output" of certain transitions. Oops! (Why, it must be an
output, because it's coded in some "output handler" function in the state
machine implementation).

------
syats
Another in the series "Show HN what is it that people actually learn in their
first two years of undegrad CS"

~~~
tonyarkles
You'd think that...

I did both EE and CS undergrad (we didn't have Computer Engineering at the
time). In EE we started talking about FSMs very early on, in quite a bit of
depth. In CS though, we didn't really talk about them until the Computability
course in 3rd or 4th year, and even then it was in the very theoretical Finite
Automata sense; applying FSMs to software design wasn't really a thing that
was ever covered.

From the EE material, I started loosely applying those concepts to software
design, but it wasn't until my first job in industry where I was lucky enough
to be exposed to a system that was very deliberately designed as a system of
FSMs.

We based the design of ours off of a pretty famous paper, whose name is
entirely escaping me at the moment. Damn.

~~~
matthewwiese
Are you thinking of Harel's paper "On Visual Formalisms"?

[http://www.wisdom.weizmann.ac.il/~harel/SCANNED.PAPERS/Visua...](http://www.wisdom.weizmann.ac.il/~harel/SCANNED.PAPERS/VisualFormalisms.pdf)

I'm curious to know what famous paper it is so that I can go and read it!

~~~
tonyarkles
That wasn't it... but this _also_ looks super interesting.

I emailed the mentor who first introduced me to it to see if he remembers what
it was called. Watch this space!

------
dstalli
Check out statechart.js. It is a implementation of a Harel Statechart and it
has worked out well for my company.

[https://github.com/burrows/statechart.js/tree/master](https://github.com/burrows/statechart.js/tree/master)

------
JoachimS
Talking to some programmers the last year I was surprised that state machines
was unknown. In embedded systems, and esp in HW design (FPGAs and ASICs) you
have state machines everywhere controlling the behaviour of the data
processing (the data plane) part of the design.

I first started to really learn about finite state machines (FSMs) during
compiler class. The parser in a compiler for example is a FSM. Tools like
Bison generates FSMs based on state rules. And in general as programmers we
write code to parse stuff all the time. So how can FSMs be unknown? I'm a bit
baffled.

------
Timothycquinn
I spent a majority of my programming career developing business process
automation solutions on top of a graph database that incorporated state
management in the middleware layer as a first come citizen. State transitions
were triggered and it had strict schema.

It was amazing the amount of features we could push out with great stability
and scalability using this middleware. We build huge systems that just ran
like clockwork and was easy to explain and reason about.

Sad part of this is that the middleware is not commercially available without
buying they vendors domain specific products.

~~~
Timothycquinn
Typo: ...first class citizen...

------
topaxi
xstate is a nice javascript library which even generates charts out of your
defined states in your app:
[https://github.com/davidkpiano/xstate](https://github.com/davidkpiano/xstate)

~~~
restore24
Similarly, I have a early-stage JS library for hierarchical statecharts. It
revolves around nested contexts and an explicit message passing interface for
controlling states between parent/child/sibling. Example:

[https://github.com/jdque/royal/blob/master/test.js](https://github.com/jdque/royal/blob/master/test.js)

~~~
mpfundstein
off-topic but why do you use 'let' instead of 'const'? In royal.ts you do that
all the time even though you variables don't change! Is there a reason for
that?

~~~
braythwayt
I have no idea why they did it, but I have argued for quite some time that
const has very little practical value, because its effect is always lexical
and local.

To demonstrate that this is so, I suggest that we can write a processor that
converts all lets to consts where possible. I also demonstrate that this is so
by asking, "What bug will const catch that our tests will not catch?"

_Immutable Data_, on the other hand, is marvellous. Immutability has nonlocal
effects, and it is not something that can be trivially verified.

~~~
mpfundstein
I agree with your assessment, but for me it is a message from the programmer
to the reader. Hey this value will not be re-assigned during the following
scope block. If I see a let, I know I must be careful. Of course this doesn't
apply to properties of objects ... which is a pity!

------
vijucat
The last time I looked at this (when having to deal with spaghetti-like
execution flows through an Actor-based code base), I really liked the ideas of
model checking with Colored Petri Nets and code generation
([http://cpntools.org/](http://cpntools.org/)), and the TLA+ language.

------
CamperBob2
TIL that VHDL can be _more_ readable than Javascript.

~~~
marcosdumay
Just wait until you start connecting things with different types by mistake
and watch the weird results you'll get.

------
joveian
No JavaScript support but for nice finite state machines in C, C++, C#, D, Go,
Java, and Ruby there is Ragel:

[https://www.colm.net/open-source/ragel/](https://www.colm.net/open-
source/ragel/)

~~~
rurounijones
Worth pointing out that the ragel parser was used to create a pretty
bulletproof HTTP parsing implementation in the mongrel webserver. I think that
implementation is still used in other http servers.

------
nateroling
After playing around with some state machine libraries, I find a simple switch
statement against a State enum to be the most straightforward approach.
Especially if your language can guarantee an exhaustive switch.

~~~
ensiferum
Indeed.

------
braythwayt
A colleague raised the point that state machines (or their richer variations)
work best in models with low cohesion.

Anybody here have some thoughts/experience with this point of view?

~~~
ahartmetz
I have related experience with QStateMachine versus hand-written (state
variable(s) + switch + some freeform manipulation): if your state machine is
"pure", using the framework is nice. If your state machine needs certain
interesting transitions such as undo which don't fit in, you may be better off
writing it yourself. If it fits at all, a funny state machine is better than
no concept for your state variables. You still get most of the benefits.

I guess domain-specific transitions like undo and cohesion mean similar things
to state machines: requirements that don't cleanly fit into conventional state
machine models.

------
emodendroket
I'll admit it: I always had a kind of murky idea of how you might use state
machines in a real program. This article gave me some idea. Good stuff.

------
HumanDrivenDev
When people talk about state machines, do they mean deterministic finite
automatons? Because i can see a lot of ubiquity in state transition tables in
code, but less use in deciding whether to reject or accept a sequence of
states which is essentially what a DFA does.

~~~
twtw
Not usually. "State machine" is typically used to refer to the more general
concept of a finite state machine, which includes Mealy and Moore automatons.
DFAs typically are not viewed as having an output (or arguably a single bit
for the whole input sequence that represents acceptance), while FSMs can have
outputs on each transition or in each state, which means it can induce some
action.

~~~
HumanDrivenDev
So people basically mean a transition table/function, but without the start
state or accepting states?

~~~
twtw
No. They mean a set of states, a set of input symbols, a set of output
symbols, an initial state, a transition function, and an output function. The
output function maps from the state to the set of output symbols (or sometimes
from the state and input to the output).

~~~
HumanDrivenDev
Is there a formal name for this?

~~~
twtw
It's probably closest to a finite state transducer. No guarantees that what I
described above is exactly the definition, though.

------
pknerd
Interesting.. wonder whether there's any Python implementation ?

~~~
mogsie
Two: * [https://aleph2c.github.io/miros/](https://aleph2c.github.io/miros/) *
[https://github.com/AlexandreDecan/sismic](https://github.com/AlexandreDecan/sismic)

------
rs86
How much of developers do not know what a state machine is?

~~~
aidenn0
At least 90% by my observation.

~~~
billysielu
This is the key point IMO. Putting stuff in your code that developers don't
understand is a RISK.

------
KaoruAoiShiho
Font on this website is so thin that it's unreadable.

