The Rise of the State Machines
smashingmagazine.com
smashingmagazine.com
Especially in hardware implementations there are also Medvedev machines where the output is the state vector or part of it, i.e. the output function is the identity function. As far as I can tell that is also where the distinction originated from because they have different critical paths resulting in differing maximum clock frequencies. For software implementations the distinction seems not really relevant.
There is definitely a learning curve to state machines, and even more so with statecharts/UML. It's much, _much_ easier to start coding an application from a bottom-up approach (start coding, colocate app logic wherever it's needed, refactor later) than a top-down approach (systematically plan the entire higher-level behavior of your app's various parts before writing a single line of code). That's why it's slow to catch on in the application development (web + native) part of the tech world.
However, in game development, hardware development, etc. state machines and statecharts are more commonly used. To me, the ability to declaratively structure your program's behavior as a directed graph opens the door to the possibility of being able to automate integrated tests (simple path/shortest path/etc. algorithms), statically analyze logic (are all states reachable? are all events handled?), optimize paths, add and remove features without worrying about if some other part of the application will be adversely affected, have smarter analytics, visualize app state, and much much more.
I know there's critics to FSMs where other more idiomatic language-oriented approaches would suffice (I myself absolutely detest the OOP state pattern - it's a needlessly imperative, hard-to-analyze state machine), but I think if developers further understood and saw benefits to functional, declarative, reactive programming and statecharts (a huge improvement over conventional FSMs), application development as a whole could reach a new level of efficiency and robustness.
In my view, the concept of a finite state machine is a simple one with essentially no learning curve. It is a straightforward concept. I would never hire anyone that described experiencing a learning curve for this concept.
The idea of "when an event occurs, the state changes" might be a natural one, but there's many things about FSMs that are somewhat of a learning curve: self-transitions, sink states, Mealy vs. Moore machines (and their equivalence), non-deterministic FSMs (and converting to deterministic FSMs), optimization algorithms, path-finding algorithms, implementation (imperative, functional, regex-based, etc.)
Instead, I use 'duff devices' variations of it (in C) which breaks down the machine into code that looks 'linear' enough, but is in fact, a state machine without the drawbacks.
I've implemented quite a few protocol stacks using that 'trick' and it's still very nice to read/maintain -- the good thing is that it roughtly looks like a coroutine/thread, without any runtime requirements, so will work just fine on embedded systems as well. Same as coroutine/state machines, don't make your 'states' too 'long' or CPU intensive, you'll have the same consequences.
There's an implementation floating around called 'protothreads' [0], but you can really do pretty much the same with a handful of macros.
That's how state machines first clicked for me, and it blew my mind. And this keeps happening, when somebody mentions it in code review, somebody's mind is usually blown.
So the more people read about this "boring" subject the better. Although the (non)deterministic finite automata (DFA/NFA) regex engines are a super interesting read IMO: https://swtch.com/~rsc/regexp/regexp1.html
But this article also describes how the data handling is processed, which seems to be totally different from what i was thinking about
- does the turnstile example in the article actually need a state machine? When you insert a coin it unlocks, when you push it locks. No need to remember the state you are in.
- in the data-fetching example, it says that in the "fetching" state it is not /accepting/ any clicks. But then shouldn't this be explicitly specified in the state machine, by having the click event loop back into the fetching state? I think it would be less error-prone and more systematic to account for all the events in all the states.
Whether or not this situation needs a "state machine" is debatable, but you do need to remember the state. In this case, a simple boolean "isLocked" could suffice.
I'd love to hear if others have tried using a state machine.
It uses Java but is applicable to any language because it's a design centric approach. In particular, lectures [2] [3] [4] [5].
It relies on a very lightweight notation and presents a choice of 4 design patterns (not just GoF State) to synthesise the code directly from the design [3].
[4] shows how to apply invariant reasoning to State Machine design, which is an extremely powerful reasoning tool.
[5] is very interesting because it explains how to deal with structured traces, which are modelled as streams using a regular grammar. This turns out to be a very simple but powerful design approach that is applicable to many situations, and very straightforward to implement using JSP (nothing to do with Java, stands for Jackson Structured Programming). Because this is basically a parser (at a very abstract level), the course then follows naturally to the FP paradigm.
It also includes a couple of very cool hands-on exercises:
Multipart file transfer [6] [7]
Midi piano player [8]
In fact, the whole course is outstanding.
[1] https://ocw.mit.edu/courses/electrical-engineering-and-compu...
[2] https://ocw.mit.edu/courses/electrical-engineering-and-compu...
[3] https://ocw.mit.edu/courses/electrical-engineering-and-compu...
[4] https://ocw.mit.edu/courses/electrical-engineering-and-compu...
[5] https://ocw.mit.edu/courses/electrical-engineering-and-compu...
[6] https://ocw.mit.edu/courses/electrical-engineering-and-compu...
[7] https://ocw.mit.edu/courses/electrical-engineering-and-compu...
[8] https://ocw.mit.edu/courses/electrical-engineering-and-compu...