13 ms·
Why Developers Never Use State Machines (2011)
- nailer 9y agoCan't read the article as site is down but: fear of the unknown, along with some of the unnecessarily complex language around the topic. I got over both of these and now use state machines in production where they make sense as a model.
- theatrus2 9y agoDevelopers use state machines a lot more than they would admit to. Often code would be more readable if the state machine was succinctly defined.
- nathanyo 9y agoThere's a lot of truth to this statement in my experience. I just finished rewriting my homework for my operating systems course and the first version looks awful compared to when I rewrote a chunk of it as a state machine
- s_m_t 9y agoI don't think I've ever programmed anything more than a hundred lines without a state machine...
- RobLach 9y agoIf you've ever do any game programming you'll be drowning in state machines.
- signa11 9y agonetwork protocol as well, hell, any non-toy network application ends up containing a state machine either implicitly or explicitly
- duxup 9y agoAs someone who troubleshot networking issues for years, god bless you.
- escapecharacter 9y agoGesture detection/interaction here. All state machines all the time.
- eeks 9y agoLife cycle management, process synchronization, lockfree data structure, user-space networking... I can't remember the last time I didn't use a state machine.
- mozumder 9y agoVHDL/Verilog as well, but that's completely obvious. I've been using state machines for Javascript UI elements.. really simplifies things.
- taneq 9y agoOr control systems (which is remarkably similar to game programming, really). Basically anything that needs to model on control a system which changes state over time. Sometimes it gets a bit too much, though, and people start seeing every task as a nail for a state-machine hammer.
- AstralStorm 9y ago
- grzm 9y agoDiscussed at the time (over 90 comments): https://news.ycombinator.com/item?id=2949543 https://news.ycombinator.com/item?id=2949543
- rxhernandez 9y ago> I am the only kind of developer there is and so therefore I will speak with authority as to what all developers do. I use state machines regularly when producing performance statistics where I need to individually isolate many history dependent outcomes in a large sample space. I tried doing it without them and ended up with unreadable and thus unmaintainable buggy code. Never again.
- liveoneggs 9y agohttp://erlang.org/doc/man/gen_statem.html http://erlang.org/doc/man/gen_statem.html
- s4vi0r 9y agoTraditional programming languages and imperative thinking don't lend themselves to writing state machines, so its not really that surprising that they're under utilized. Its kind of frustrating constantly reading posts where people shit on functional programm(ers|ing) for being too ivory tower-y or whatever, when its kind of hard not to be when a lot of the older FP guys have spent the last like 20-30 years going "yo this is dope you guys should really be doing this" and getting largely ignored. State machines are super commonly used in languages where you can (easily) construct ADTs and pattern match on them.
- vvanders 9y agoPlenty of imperative domain spaces use state machines, gamedev and the like come to mind in particular.
- pdelbarba 9y agoSimilarly with embedded development. We use them for just about everything from communications to scheduling. I think the subtext here is that state machines are just rarely used for web/mobile...
- DCoder 9y agoOne simplistic state machine in web/mobile is mouse/swipe motion handling – mousedown transitions into "in motion" state, mousemove tracks that state, mouseup transitions into "finished motion" state, runs event handlers, and transitions again into "idle" state.
- vvanders 9y agoYup, I'm in the middle of writing a packet radio protocol and it's mostly just nested state machines.
- jjjensen90 9y agoDefinitely true for gamedev in my experience. I don't think I've worked in a game code base of nontrivial size without seeing some implementation of state machines.
- vortico 9y agoYou could even go as far as saying that a class in some forms is a state machine. Networking is a huge application of state machines. Microcontrollers usually have a small state and step through a switch statement in an infinite loop. OpenGL is a state machine. If you write a state machine, it's easier to implement it "perfectly" than other methods, and other parts of your program are able to interact with it in more straightforward ways.
- greenleafjacob 9y agoErlang stands out for me as having a state machine library in the standard library (gen_fsm).
- liveoneggs 9y agonow gen_statem
- nwatson 9y agoState machines are essential for a lot of programming tasks -- I wish they were more explicit more often, because there always is an implicit state machine lurking in there somewhere, and code would be cleaner with the state machine made explicit. For example ... I was brought on to work at a startup a few years ago by an old-time acquaintance that was CEO of a startup ... the company's proposed product sounded interesting, and I believed in her skills and background and had decent rapport with her. I was wary of the VP Engineering and a few others, but it was to be my first post-move-out-of-SF-Bay-Area remote startup job and I thought I could make it work. I show up in Santa Clara, CA to make sure I really want to do this ... and after joining we spend the next few days going over architecture, implementation-so-far, etc. Part of the product's job is to discover and categorize servers and networking devices, the basic software deployed on them, etc. Apparently this aspect has been in design/implementation for several months, but it's not working very well, and the problem and approach aren't articulated very well. I have a chance to look at the code a bit. I eat lunch with the CEO and she asks me how I'd approach the problem, and I advocate breaking everything down into state machines with well-defined transitions ... both for interacting with the environment, and for storing info in the back end -- there's ample opportunity for things to go wrong, to require retries, etc., and tracking these interactions with state machines makes it much easier to efficiently and quickly deal with the environment and back end in asynchronous fashion, and to separate different levels of discovery (network / IP; finding credentials that work; OS determination; software inventory; storage inventory; etc.) much easier. In the next day's architecture discussion I then hear the VP Engineering use a few of my words and draw a few poorly formulated diagrams that don't do the task much justice ... it's apparent the CEO has discussed the problem with him and urged a new look. I had to start work on my piece so I didn't follow their developments much, but I heard later they actually purchased and licensed for significant money a "finite state machine package" of some kind. All they needed were ENUMs, (preferably async-result) functions to try something out, and then transitions between enums based on the results. That discovery code was always buggy, never did work right. That was one of many fiascos. There were so many other fiascos, and they all cost me lots of sleep, some of my sanity, and some self-respect. I lasted almost three years there (some early players were pushed out but the product never really got better). I would have been happier quitting the first week, or better yet never joining.
- thinkloop 9y agoFast forward 8 years and everyone on the front end is using state machines with the rise of react/redux et al.
- ricardobeat 9y agoA reducer store is not a state machine since both the transitions and states are loosely defined. That said, at this point I think it's actually better for UI, despite the verbosity and lack of formal correctness.
- acemarke 9y agoIt's also worth noting that you can absolutely _use_ state machines to implement your reducer logic :)
- aj7 9y agoOf course developers whose last experience with state machines was in a college course won’t use them. Just read some of the comments below the article on storks.com. Labview developers use state machines extensively, because the implementation is graphical, beautiful, and prevents loose ends.
- grzm 9y agoLooks like you got bit by autocorrect: s/storks/skorks/
- planteen 9y agoI used to do VHDL for FPGAs, where you basically have to use state machines. LabView is that way too, being a dataflow language. But I don't know how much LabView I've seen that I would call beautiful. Maybe if one considers spaghetti beautiful. ;)
- housel 9y agoOne of my go-to interview questions is "Can you tell me about a time when you've used an explicitly-modeled state machine in your programming?" Our work, heavy in embedded devices, network protocols, and parsing, is so full of state machines that I wouldn't want to hire someone who wasn't comfortable using them.
- ssoft 9y agoFor equipment automation i am using end-state player which accelerate our development at least in 3 times. Why? There are three levels of hierarchy: conception level, detail, gui. All of these levels are independant to earch others, for example, arhitector can invented new conception with some fake elements which will be substituted in some future stages. Software developers who are making new elements (with parsers, new libraries and so on), regarding to conception above, are not intersected with conception and gui levels. In its turn gui developers use only state schema with all defined properties or data which are belong to every state.
- jimmaswell 9y agoCompilers and games are two areas I've used them a few times in.
- kchoudhu 9y agoOrder/bid management in markets is also a case where they shine.
- AstralStorm 9y agoIs that why orders tend to get stuck in "Delivery" state all the time?
- kchoudhu 9y agoNot sure what you're referring to?
- dominotw 9y ago
- IamNotAtWork 9y agoI really don't like state machines because if you need to add a new event, each of the states need to be updated to handle that event. If you add a new state, you have to figure out how to handle each of the transitions from other states. So as your states grow, the maintenance on the developer's side grows faster than linear. Additionally, I find that I cannot understand how the program works without actually drawing out the state machine diagram if I come across it the first time, so there is a bit of a learning curve. It's also a nightmare to test because of all of the states that need to be tested. So in summary, not a fan. Like recursion... if it feels natural then use it, but I don't go and try and turn stuff that isn't a SM into one or turn something that can be done as loops into recursive function for fun.
- ricardobeat 9y agoBoth of your concerns seem to be nicely addressed by statecharts (nesting to constrain relations + visualization): https://medium.freecodecamp.org/how-to-model-the-behavior-of-redux-apps-using-statecharts-5e342aad8f66 https://medium.freecodecamp.org/how-to-model-the-behavior-of... (haven't used this yet)
- viraptor 9y agoI don't understand the issue very well... If you have a new event, you either have to handle it in the state machine or some other way. Any place where the event doesn't apply should cause an appropriate failure. Same with new states - you have to write those transitions in some way. You can use macros/abstractions/whatever for simplifying many cases. But none of that code really disappears when you don't use SM.
- sgt101 9y agoI think the concern is that the update is across the code -dispersed in the code base. But this only applies to legal events in all states else the default behavior should be invoked. If a new event that is legal in many states is created then you have to handle it everywhere anyway, and my experience that if then structures fill with bugs fast in this case
- 9y ago
- sytse 9y agoThere was a reference to a Shopify blog post that 404s, the new url is https://shopifyengineering.myshopify.com/blogs/engineering/17488160-why-developers-should-be-force-fed-state-machines https://shopifyengineering.myshopify.com/blogs/engineering/1...
- CarVac 9y agoI use state machines in UI.
- userbinator 9y agoI would hazard a guess that there are decent state machine libraries for most languages that you can use I think this is already part of the problem of complexity --- when I think "state machine", what comes to mind is a loop and a switch with some gotos in the cases. Definitely not a library. If you think "I need to use a state machine" and your next thought is "I need to find a library for that", then IMHO you're definitely doing it wrong.
- JoachimS 9y agoAgreed. When I worked on last years Advent of Code problems (amazingly good problems btw) I ended up writing many solutions as small FSMs. Typically you read a token, moved to a new position and then acted based on the current state and the token, position. You don't need a library since the code is just a few switch statements. https://adventofcode.com/2017 https://adventofcode.com/2017
- AstralStorm 9y agoAnd then everything ends up in Error state with no history. At least function stack has stack traces...
- zaarn 9y agoFSM's usually don't have error states, you tend to crash them first. Though that is preventable, mostly because the code you run is inbetween transitions and that will return very nice stack traces. Otherwise, you don't need a trace of a state machine, the state you're in and the current transition should tell you exactly where it's breaking. If it doesn't, chances are you're breaking state machine definitions by storing wildly complex state outside the machine.
- sfilargi 9y agoErlang OTP’s gen_fsm and gen_statem are great for implementing state machines. Mind you however, the immutable nature of variables really helps.
- moscovium 9y agoWe tend to use state machines for massively asynchronous operations like order management (with days between updates), as well as a home-built library for handling the task. It's incredibly fault tolerant and offers really easy abstraction and automation.
- niftich 9y agoState machines are not a first-class concept in most currently popular high-level programming languages, so when you implement one, you're merely adhering to a design pattern. While a design pattern is a perfectly legitimate strategy to organize code, it's a manual exercise with no help from the compiler: it's a workaround for the language of choice not being high-level enough for the concepts you're coding. This is why frameworks useful: they intentionally constrain the problem space, so one can focus on just unique behavior. When one reaches for a framework, they're often using someone else's state machine. Game loops, GUI event loops, or network protocol states are applications of this same pattern. In some greenfield development, frameworks have a poor reputation for removing developer control. This stems from a misunderstanding: that having a large amount of choices in organizing code is a desirable goal. It very rarely is.
- vinceguidry 9y agoIn between design patterns and frameworks are the perfectly legitimate solution of libraries, which is the most common approach I've seen.
- tonylinn80 9y agolol, interesting read. I used to work on a graphics project with a state machine at its core, and user actions are defined to trigger state transitions
- danmaz74 9y agoUsing (explicit) state machines in Rails is so easy, thanks to the gem of the same name(1), that we use them very often, with good results. I think that ease of setting them up and integrating them in whatever framework/language you use is a very important factor in their adoption. 1 current version: https://github.com/pluginaweek/state_machine https://github.com/pluginaweek/state_machine 1a original unmaintained version: https://github.com/pluginaweek/state_machine https://github.com/pluginaweek/state_machine
- mmilano 9y agoAds that auto pay audio on a developer blog, really?
- forgotmypw 9y agoDisable JavaScript, problem solved. Bonus: Pages written by developers who don't know/care about graceful degradation appear blank, so you don't have to waste time reading them.
- aplorbust 9y ago"Why Developers Should Be Force-Fed State Machines" https://shopifyengineering.myshopify.com/blogs/engineering/17488160-why-developers-should-be-force-fed-state-machines https://shopifyengineering.myshopify.com/blogs/engineering/1... I always thought all computer science students had to take a compilers course, or some course on theory of computation that required some level of competency in lexing/scanning/tokenizing and parsing. This blog post appears to be directed at "web application developers" who lack "awareness about state machines".
- mikekchar 9y agoQuite a lot of software developers were never CS students. In fact in some industries engineers are very much desired as programmers. In others, math and physics majors are desirable. And even when we exhaust all of those, I don't think there is any need to look down our noses at those who took an apprenticeship style approach to the industry. In fact, in my career I have met many CS graduates who dismissed grammars and automata as irrelevant and insisted on writing that parser for a context sensitive language using regular expressions and about 400 global variables (and they still can't understand why it doesn't always work). Besides some of us "web application developers" actually have CS degrees and have worked in half a dozen other industries besides "web application development". Programming is programming and a programmer is a programmer. There's a lot to learn and you have to stay humble your whole career. Not everybody manages it easily.
- noir_lord 9y agoVery nicely put. I've worked with lots of programmers over the years and a CS degree has been a very poor indicator of their ability to program in the large.
- aplorbust 9y agoThe ECMAScript standard actually has a section on "Context- Free Grammars". In that section and subsequent sections there is discussion of tokens, terminals, nonterminals and productions. If a web application developer using Javascript read these sections of the language specification and became curious enough to do a little outside research on the terminology, then perhaps it is forseeable she might encounter the notion of a "state machine".
- PSeitz 9y agoI use a state machine for text https://github.com/BurntSushi/fst https://github.com/BurntSushi/fst
- dwarman 9y agoI'll echo the observation: datacomms protocol parsing and generation are nothing but state machines.I started in that domain back in 1973 or so, and some configurations - statistical multiplexors for example - may be running upwards of 34 FSM's concurrently and independently. And that with a mix of multiple instances of one protocol. So I developed a cooperative multitasking pattern that ran on a virtual OS scheduler. Indeed in some systems it was the real OS. State variable is a function pointer to a function that returns its own protoype function pointer. Arguments include event, plus data plus state context. Supports submachines too. Still using it. No switching complex stack contexts, runs fast.
- acrive 9y agoThe state machine is very near at Design by contract pattern. There are states, preconditions and other stuff. The question now will be "Why developers never use design by contract pattern?" :) https://github.com/nhatminhle/cofoja https://github.com/nhatminhle/cofoja for example
- AstralStorm 9y agoDesign by contact is a lot more general. You can have preconditions and postconditions in stateless code. And statelessness is the best way to handle concurrency. When stateful and concurrent, you get to handle outdated requests intelligently and with as little blocking as possible.
- kabes 9y agoBut most developers do write regular expressions, which are also finite state machines.
- dis-sys 9y agoTry consensus libraries widely used in modern distributed systems, whether it is paxos or raft based, just pick your favourite one, both are heavily based on the concept of state machine.
- cimmanom 9y agoIsn't one component of this that so many people develop for web now? And that HTTP is inherently stateless. That means we have to resort to hacks to store state (databases, cookies) - and like most hacks, those are fragile (such as assuming a single instance of state and then breaking when the user opens another copy of the site in a tab). With the rise of single page apps, there's a more coherent concept of state on the front end, but that doesn't fix the fragility of the server side portions.
- naasking 9y ago> That means we have to resort to hacks to store state (databases, cookies) - and like most hacks, those are fragile (such as assuming a single instance of state and then breaking when the user opens another copy of the site in a tab). In principle, there's nothing fragile about the types of state you describe, but most web frameworks don't impose enough restrictions to ensure this state is used correctly [1]. [1] something like this would work, but it's not the only option: http://cs.brown.edu/~sk/Publications/Papers/Published/mk-int-safe-state-web/ http://cs.brown.edu/~sk/Publications/Papers/Published/mk-int...
- lupin3 9y agoOne of the most refreshing experience I have had recently is to map Websockets to some finite state machine implemented on an actor model (namely Akka FSM): straightforward and fitting together naturally.
- tanilama 9y agoState machine is useful when it is useful. I can see for certain string matching problem, internal management of certain data structure, it is going to be a handy improvement. However, specifically in web development, it is discouraged because the nature of the application itself. Think hard how states are managed in a typical service, the real states live in a DB. Which makes state machine less useful because the ground truth is stored elsewhere, and should be updated by DB's own primitives. And in a distributed settings, failure is something you have to put into consideration. Making your service stateful is a red herring that brings all kinds of operational troubles. That is why the dominant approach people seems to agree upon is to keep application stateless while delegate all dirty work to DB. So realistically I think state machine is useful to write certain helper routines in a non-persistent, single-thread scenario, for the ease of reasoning, but really should be limited within the lifecycle of a single API call.
- mixmastamyk 9y agoWould like to read more on this subject if anyone knows any resources.
- ggambetta 9y agoI rarely (if ever) use state machines explicitly, but I do use them relatively frequently to reason about the behaviour of a system. A paper tool rather than the way I actually write the code. I use flow charts and sequence diagrams in a similar way.
- notacoward 9y agoThe biggest source of resistance that I've run into is not with the concept of state machines but with common implementations. Two examples: * A quarter-century ago I implemented a cluster membership protocol and coordination system as a state machine. This provided great benefits in terms of verifiability, extensibility, etc. but some developers complained while the current state was explicit the history of how we got there was not. Adding a history mechanism helped, but frankly it still wasn't as good as the stack traces we'd had before. While the benefits far outweighed the drawbacks, this drawback was quite real. * On my current project, a critical component (not dissimilar to the the one in the previous example) was implemented by someone else as a state machine. Besides the fact that the semantics of that state machine are unusual and undocumented, and that this state machine also lacks a history mechanism, developers over the years have been wildly inconsistent about which actions occur on which state transitions and how other information is saved/restored "off to the side" between transitions. The result is worse than spaghetti. It's like a chunky goulash that nobody can digest, which is why we're rewriting that component from scratch. Based on these experiences, I suggest a few rules for implementing a successful state machine. * Make sure the state machine is properly documented - what the states mean, what the events mean, how a transition is selected when multiple might apply, etc. * Make the control flow discoverable by providing a history mechanism. * Make the data discoverable by capturing all relevant flags and secondary state in a structure that's passed to the code implementing transitions. * Verify the heck out of your state machine every time it changes. Make sure that every path terminates, using timeout events as needed, and that termination includes proper resource cleanup. If appropriate, verify that multiple concurrent invocations can't race with one another and violate the invariants you've checked within each. This verification is much easier to do with state machines than with other approaches, and you should take advantage of that.
- bsenftner 9y agoI find the biggest resistance is the obvious fact that implementing a state machine requires planning: mapping out the goals, identify which are your formal states, map out the transitions, evaluate the overall logic requirement and then design the state machine's data structure and classes... All the "planning" is the opposite of what most "code slinging macho programmer personalities" want to do; they want to jump into coding an just wing it. That is the real issue here: Undisciplined development.
- cbetti 9y agoOne thing formal state machines make difficult is component reuse. Let's say you have a music playback control component you wish to reuse across a feature rich player, as well as a mini playback controller. You COULD just use the full state machine to power the mini player, but most of the transitions would be unused. It would be unclear to the next maintainer which aspects were needed for each use case, thus making the state machine brittle. Instead, you can write an independent playback progress/state class, and reuse it in both players via composition and proper layering of functionality. By hiding the playback state from the rest of the player and exposing control of it's state via an interface, you've gained functional reuse. Reapply the same pattern for all components of your players and you'll find that your product is safer to change and easier to understand than if you had built a complicated formal state machine covering all possible music player use cases.
- bsenftner 9y agoAh... your "independent playback progress/state class" is another state machine, just better with an architecture that suits your use case. "Full state machine" is a misnomer and common misunderstanding of the power of state machines. Any state machine bordering on complexity that is hard to manage can be broken into multiple smaller, easier to grasp and manage state machines. And state machines transparently integrate with functional programming, so any ideas contrary to that is yet another misunderstanding of them.
- cbetti 9y agoI wouldn't consider this class a state machine in the sense described in the paper. Any class managing state exclusively is an implicit state machine, no?
- Jtsummers 9y agoThis was a nice thing in the example from Raganwald's blog post. The `transitionsTo` decorator: function transitionsTo (stateName, fn) { return function (...args) { const returnValue = fn.apply(this, args); this[STATE] = this[STATES][stateName]; return returnValue; }; } By separating the state transitions from the state actions in this way it allows the functional components to be reused much more easily. You can construct the miniplayer using only the states you need with only the transitions you need (rather than obscured/hidden capabilities).
- AstralStorm 9y agoA major problem with any state machine is that they tend to fall apart or become major bottlenecks if concurrency is required... It is still shared state, a thing to minimize. Usually message passing (current buzzword: reactive) approaches work much better.
- Jtsummers 9y agoWhy would state machines become a bottleneck with concurrency? This is definitely counter to my experience so I'm curious to see examples demonstrating this.
- dragonwriter 9y ago> A major problem with any state machine is that they tend to fall apart or become major bottlenecks if concurrency is required... One of the classic ways of architectural a concurrent system is as a collection of sequential processes implementing message processing loops as state machines. If you mean that state machines can't deal with internal concurrency, that's not true either. Leaving out concerns about unmanaged state (mutable data not reflected in the state of the machine), a state machine provides a clear framework for managing concurrency: (1) an unlimited number of events that produce self-transitions can be processed simultaneously; (2) an event that would be processed the same in the start and end states of all currently running events and whose end state would not alter the processing of any currently running event can be processed concurrently, (3) an event that would not be valid in the end state of any currently running event is invalid, (4) any other event cannot be run concurrently, blocks new events entering processing, and must be evaluated for validity after each running event completes (it may become either runnable or invalid). The last is a kind of bottleneck, but it's usually not introduced by the state machine so much as a feature of the domain.
- lph 9y agoSaying that developers "don't use" state machines just because code isn't littered with things like instantiations of machine and state classes is an interesting point, but kind of glib. I use state machines all the time as an abstraction to reason about programs.
- ncmncm 9y agoI use state machines all the damn time. Am I, then, no developer? Maybe you meant to say that only competent developers use state machines. But that would place you outside their august company, leaving us little reason to credit your observation. In that world, the absence of state machines in one's code would reliably indicate incompetence. But in fact, by definition, there is no computer program on God's green Earth that is not a state machine. Programming languages were created specifically to make the state machines they compile down to look more intuitive and less like, you know, state machines. So the observation is really that our programs usually look the way they were intended to look, except when we abuse our language in pursuit of performance, elegance, or other consensual delusion.
- ssoft 9y agomay be some of developers don't know this technique and more evident that they never tried to work with end state machines. I am using state machine long time and made my own script player for SM, unlike to others SM i am using it in different implementation from web till equipment automation. https://github.com/series6147/ProcessPlayer-state-machine https://github.com/series6147/ProcessPlayer-state-machine