Live data from Hacker News

Why Developers Never Use State Machines

skorks.com

51–60 of 96 posts

Re: Why Developers Never Use State Machines

#51
post #23

Having used state machines a lot for embedded development, I find that they have one huge drawback: the resulting C code is unreadable, which turns maintenance into a nightmare. SM have a key quality: they are a compact and unambiguous way for specifying a behavior. If your system's behavior is set in stone, it's worth specifying it as a SM and implementing it as one. This SM is also great to include in a spec, stand…

Is it really so unreadable? It's not crystal-clear like perfectly linear code as you sometimes have to follow the flow of the state machine through various functions, but syntax-wise once I discovered structs and typedefs, managing state was simple and concise.

Re: Why Developers Never Use State Machines

#52
post #23

Having used state machines a lot for embedded development, I find that they have one huge drawback: the resulting C code is unreadable, which turns maintenance into a nightmare. SM have a key quality: they are a compact and unambiguous way for specifying a behavior. If your system's behavior is set in stone, it's worth specifying it as a SM and implementing it as one. This SM is also great to include in a spec, stand…

Exactly my experience. Over the years we've tried many different ways of coding state machines and it's very hard to keep them readable. Still we continue to use them, the pros outweigh the cons.

There's a pretty interesting RTOS approach based on state machines (www.state-machine.com, no less) that uses single-stack run-to-completion "tasks". They also have some kind of wizard approach to generate code but I haven't had enough time to evaluate it.

For anyone who finds state machines in HLLs unreadable, try looking at a state machine implemented in ladder logic on a PLC!

Re: Why Developers Never Use State Machines

#53
post #23

Having used state machines a lot for embedded development, I find that they have one huge drawback: the resulting C code is unreadable, which turns maintenance into a nightmare. SM have a key quality: they are a compact and unambiguous way for specifying a behavior. If your system's behavior is set in stone, it's worth specifying it as a SM and implementing it as one. This SM is also great to include in a spec, stand…

...the resulting C code is unreadable...

It seems to me that, if all of your state machines follow a common pattern, seeing enough of them would make it easier to decipher any given state machine. To a programmer who's never seen an event loop with states represented in a switch block or as function pointers, it may seem unreadable.

Re: Why Developers Never Use State Machines

#55
post #44

Can anyone recommend a good introduction to using state machines in code? Especially something in javascript/python? I know what an SM is and how it works, I just want to know how to use an SM library to actually do all these cool things.

A lot of the IBM Developer articles are apparently crap, but I found this one interesting and well done, some years ago.

The article date looks different, now, and IBM has redesigned the site since I originally read it, but I think -- at a glance -- that it's the same article.

http://www.ibm.com/developerworks/library/wa-finitemach1/

http://www.ibm.com/developerworks/web/library/wa-finitemach2...

http://www.ibm.com/developerworks/web/library/wa-finitemach3...

Re: Why Developers Never Use State Machines

#56
post #23

Having used state machines a lot for embedded development, I find that they have one huge drawback: the resulting C code is unreadable, which turns maintenance into a nightmare. SM have a key quality: they are a compact and unambiguous way for specifying a behavior. If your system's behavior is set in stone, it's worth specifying it as a SM and implementing it as one. This SM is also great to include in a spec, stand…

I am not sure that the accusation of unreadability is valid. The advantage of a state machine is that you can enforce invariants - if you're in state X, then you know categorically that preconditions { X0,X1... Xn} have been met.

Any enum with clear transition logic is effectively a state machine. However, if you try to implement SMs as separate classes/objects with explicit transition functions, than it does become an unreadable mess. The logic in your code stops representing behavior. I think that's what the grandparent post refers to. Also, "explicit" state machines don't allow to use recursion, which can made code much more readable.

Re: Why Developers Never Use State Machines

#57
State machines are useful because they're 1) computationally fast 2) simple to implement 3) easy to read [up to a certain size]

The big problem with state machines relates to the number 3 and regards the general concept of "state". Managing state is the challenge of computation! As you add states and transitions, the complexity increases dramatically, exponentially in some cases. This is why novice programmers struggle to manage developing large applications: they depend on global state and side-effects to perform computation rather than creating isolated components (classes, methods/functions)

That is why we use higher level abstractions provided by programming languages. We use state machines unknowingly in our code every time we have a switch or a conditional statement. When we use design patterns such as the GoF state pattern, we are implementing a state machine. When we build closures in functional languages, those can be considered state machines (in an abstract way). It's just that we're doing it in a more intuitive, higher-level way.

What I'm getting at is that computer programs inherently contain state machines. Recall from computer science that a a stored program computer (e.g. Turing machine, Von Neumann architecture) is just a state machine with an unlimited memory. When we deal with more complexity, it's not wise to attempt to model the problem with a state machine. Using the constructs of a high level language are easier to deal with and underneath the hood, the appropriate state machines are being created.

Re: Why Developers Never Use State Machines

#58
post #23

Having used state machines a lot for embedded development, I find that they have one huge drawback: the resulting C code is unreadable, which turns maintenance into a nightmare. SM have a key quality: they are a compact and unambiguous way for specifying a behavior. If your system's behavior is set in stone, it's worth specifying it as a SM and implementing it as one. This SM is also great to include in a spec, stand…

The readability really depends on your tools. There are state-machines compilers that generate code with e.g. #line directives that hint to the debugger what you want, and even full-fledged IDEs that show the state-transition.

Now if there is a bug in your state-machine compiler, that can be hairy (and it does happen) but the same is true if there is a bug in your C compiler.

Re: Why Developers Never Use State Machines

#59
post #44

Can anyone recommend a good introduction to using state machines in code? Especially something in javascript/python? I know what an SM is and how it works, I just want to know how to use an SM library to actually do all these cool things.

There are other JS FSM libraries, but I ran into this one recently, which has an online demo:

The blogpost about it:

http://codeincomplete.com/posts/2011/8/19/javascript_state_m...

The online demo:

http://codeincomplete.com/posts/2011/8/19/javascript_state_m...

Re: Why Developers Never Use State Machines

#60
I use them extensively for Appointment Reminder. In addition to modeling the business logic pretty intuitively (particular types of input can cause an appointment to go from :scheduled to :confirmed, :confirmed appointments should not generate additional reminder calls but :scheduled ones should, etc), they're virtually indispensable for doing Twilio applications. I'll have more to say about that at TwilioConf (and will probably post my presentation afterwards). If you do not model call state with a state machine, anything more complicated than "Hit 1 to talk to sales, hit 2 to talk to support" turns into an ugly ball of spaghetti code with lots of sharp edges, poor testability, and crushing amounts of technical debt getting in the way of maintaining or extending anything.

After I got more comfortable with actually using them for real work (as opposed to "cute toy from CS class"), I started seeing FSMs everywhere I looked in my projects.

For one thing, they make analytics a lot easier to slot into your system. For example, I record the fact of interesting events like e.g. purchases and send it off to KissMetrics or internal analytics stuff for graphing/reporting/auditing/etc. That gets done in my controllers, and it results in a whole lot of duplicative code which I often forget to write. (It's easy to miss that e.g. if I credit somebody manually for a purchase that should count as a purchase, even though it is under admin functions rather than the purchasing pathway. After all, if I forget to write that log code, all that happens is my stats get silently borked.)

This could get fairly easily solved by having the logging code aware of the change in the user's status, which is about three lines if you have a state machine, and won't put the logging logic in 12 different places in your app or cause you to have to pollute the user model with a big ol' case statement of doom. Plus, if you want to log more stuff, you naturally go into the log logic and make it do more things when the right events bubble to it, rather than chasing down a) who "owns" the event or b) where the event happens.

Post reply on HN