Here is the initial paper from David Harel: STATECHARTS: A VISUAL FORMALISM FOR COMPLEX SYSTEMS (1987) - https://www.inf.ed.ac.uk/teaching/courses/seoc/2005_2006/res...
Website with lots of info and resources: https://statecharts.github.io/
And finally a very well made JS library by David Khourshid
that gives you lots of power leveraging statecharts: https://github.com/davidkpiano
While we're at it, here are some links to previous submissions on HN regarding statecharts with lots of useful and interesting information/experiences:
My own interest in Statecharts comes from wanting/trying to use them for UI development on the web, think there is lots of value to be had and time to be saved by using leveraging it.
Some of Miro's online writings:
State machines are pretty cool - I took a digital systems class and found that the concept is straightforward and with a little practice defining states and transitions gets a lot easier. Then implementing a finite state machine (+datapath) with something like SystemVerilog is extremely straightforward.
If statechart libraries can help you define what these states are and how data is used, that would be amazing - basically making the whole thing declarative and much less prone to programming error. Google's Paxos Made Live paper , on the engineering challenges of actually implementing Paxos, actually attests to this value in section 6.1:
Fault-tolerant algorithms are notoriously hard to express correctly, even as pseudo-code. [...]
We addressed this problem by coding the core algorithm as two explicit state machines. For that purpose,we designed a simple state machine specification language and built a compiler to translate such specifications into C++.
We believe that choosing a specification language makes it easier to reason about and modify our state machines than an explicitly coded implementation that is intermingled with the rest of the system. This is illustrated by the following experience.
Towards the end of our development of the fault-tolerant log, we had to make a fundamental change in our group membership algorithm. Prior to this change, a replica roughly went through three states. [...but] Intermittent failure turned out to be more common than originally anticipated because normal replicas exhibit intermittent failures from time to time.
Thus, we needed to change the algorithm to have two states. Either a replica was in the group or it was out. A replica could switch between these two states often during the lifetime of the system. It took us about one hour to make this change and three days to modify our tests accordingly. Had we intermingled our state machines with the rest of the system, this change would have been more difficult to make.
> Ragel compiles executable finite state machines from regular languages. Ragel targets C, C++ and ASM. Ragel state machines can not only recognize byte sequences as regular expression machines do, but can also execute code at arbitrary points in the recognition of a regular language. Code embedding is done using inline operators that do not disrupt the regular language syntax.
RubyConf 2015 - Stately State Machines with Ragel by Ian Duggan: https://www.youtube.com/watch?v=Tr83XxNRg3k
Even invented my own DSL and compiler a while back, but never really had the time to get it good enough to be useful.
If I had to do it again I might not use Ragel for either packet parsing or session state. The MySQL wire protocol is rather simple, and Ragel has a steep learning curve, which made hacking on the library unnecessarily difficult for others. At the time I was already knee-deep in Ragel for other stuff, so it was the path of least resistance for me. But for more complex state management I would definitely return to Ragel as the expressive syntax is worth all the documentation and commentary in the world. And because of how well Ragel supports embedded code blocks (including for non-blocking/asynchronous I/O designs), you can maintain proximity between critical code and the state chart directives, which improves both expressiveness and self-documentation. That's the real power of Ragel--it's source code-level interfaces. On the surface the interface seems a little clunky (no interoperability at code AST level), but in practice it's second to none.
 Of course, the second time around you already know the pain points and contours of the problem so it's much simpler to open-code an elegant, minimal solution. So it's not much of a comment on Ragel to say that I wouldn't do it again.
Also known as hierarchical state machines. (web searches) Oh, which are also called state charts. So yes, those!
I'm surprised no one mentioned this yet, but At has first class support for state charts and state machines in Qt's state machines framework.
>Because if you think harder about it, an event will usually have some deviation from doing that action. Most buttons are clickable, and when you click it, then you perform the action. However, some users doubleclick most buttons, and in those cases, rarely do you want to repeat that action.
This type of event duplication has been the source of glitches in pretty much every html5 based game. What happens is that there is a dialogue with an onclick handler and triggering the handler causes the dialog to close with an animation. If you click the dialogue again before it closes it will execute the onclick handler again. This lets you duplicate quest rewards in a lot of RPGs.
Just, please, don't implement them in Oracle stored procedures.
The main challenge for me is when a given state comes with a “Tick” method that gets invoked via current_state.Tick() - Eg, in an update method in Unity. This makes them a tiny bit more hairy to work with, and I am not certain what the best practice is to keep this very simple.
I know bob martin has a video course on creating a custom compiler to generate state machines from tables. That seems neat too
One thing that you can often get by moving the state machine a bit away from the source code as tends to be the case with these libraries is a definition that specifies I/O more concretely. In something like the Unity3D Tick() case, I/O is open-ended: All game state is available, and that state may itself impact when Tick() is called via various concerns of concurrency(timing, update order, etc.). When trying to apply a formal model it's usually a really bad sign to see a very broad "tick" or "update" callback dumped into execution - it leads towards hacky code that sets flags and uses frame boundaries to confirm events.
Game engines don't always have the best examples of these patterns, since games can so often get away with shoddy usage.