
Why developers should be force-fed state machines - Titanous
http://www.shopify.com/technology/3383012-why-developers-should-be-force-fed-state-machines
======
pacemkr
This is mostly a description of state, not of state machines.

Status, published, or paid fields on your objects have little to do with state
machines if the code is not written with assertions about the current state of
the application. These fields are just... well plain state, and no machine.

One would learn more about state machines from looking at the Ruby gem that's
linked to in the article: <https://github.com/pluginaweek/state_machine>

~~~
lgeek
I've always thought that gem's a bit silly. It makes sense to _think_ in terms
of state machines, but to code them explicitly?

~~~
pygy_
Yet another misteriously killed post, by someone who's not deadbanned:

In [1] , fleitz [2] wrote

 _Explicitly using a state machine often yields benefits in terms of
reusability and clarity. The state machine pattern also works really well with
async code where it quickly becomes unapparent what's going on._

[1] <http://news.ycombinator.com/item?id=2650347> [2]
<http://news.ycombinator.com/user?id=fleitz>

~~~
6ren
Weird, that's one of the most insightful comment here. Why would it be killed?

------
eck
State machines should be force-fed simply because they are the simplest
computational model, and if they are sufficient for a task, to use something
more complicated would be illogical. Indeed, in computer science school, they
generally _are_ force-fed, followed of course by force-feedings of push-down
automata and various Turing Machines. (And if your web app is modeled as a
very long tape, that is probably bad.)

------
tomdale
Great post. I think it is important that more developers learn the importance
of managing state. Almost every application ends up with the kind of bugs
where you have two properties set on an object that are mutually exclusive,
and you can do nothing but scratch your head and try to reproduce the steps
that got you there.

Even more important than in Rails-style server-side MVC, though, is using
state management in stateful client-side MVC, like Mac, iOS/Android, and web
applications. (See [http://gmoeck.github.com/2011/03/10/sproutcore-mvc-vs-
rails-...](http://gmoeck.github.com/2011/03/10/sproutcore-mvc-vs-rails-
mvc.html) to understand the difference.)

At least with Rails, the flow through your application is pipelined M->C->V
and the debugging is significantly easier. If you think about an iOS
application, for example, your application is starting off in a different
state every time, and is constantly being modified by the user. If you ever
get into bad state, it can be very hard for the user to recover; especially if
that bad state gets persisted to the file system.

One problem with state machines is that they grow in complexity very quickly,
and the tools that were given to most people in their CS curriculum don't help
you manage this fast growth. However, applications that are mission-critical
still need the robustness of formalized state management.

David Harel, while working on software for fighter jets, came up with Harel
statecharts, which describe a formalism for parent and child states. These are
also very popular in embedded systems, such as pacemakers, where users could
die if the system fails:

[http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Stat...](http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Statecharts.pdf)

We've been preaching statecharts pretty hard in the SproutCore community,
although largely internally at Apple, and included a built-in statechart
library in our 1.5 release. Mike Cohen, the maintainer of the SC library, has
a ton of great resources on his blog:

<https://frozencanuck.wordpress.com/category/statecharts/>

I think especially in the arena of web applications, we need to start
spreading the word about the benefits of statecharts, not least of which is
the easy ability to regenerate state from URLs. It requires discipline and
effort upfront, but so does unit testing, and I think that's a battle that the
development community has largely won.

~~~
adamesque
This is increasingly important for client-side devs as we use the History API
to transition between pages without reloading. This upends our whole
predictable state model starting with a page load and a clean slate.

Case in point: I recently built a web app / site with simple content, but very
complex page-to-page animated SVG transitions.

The _easiest_ part of the project was implementing the animated transitions.
By far the hardest part was managing UI state, since you could enter the app
from any URL endpoint.

Thing is, it was only the hardest part because I thought about it last, after
I'd built the whole thing assuming a predictable initial state. An approach
starting with a statechart might have saved me a ton of trouble.

------
Stormbringer
Last time I ran into a business process coded as a state machine in the wild
it was this horrible mess of code that no one could understand. After staring
at it for a while, going through it line by line... finally the lightbulb went
off and I was "oh! It's a state machine! I know what they're trying to do
now!"

Kind of a Neo "I know Kung Fu" moment.

Unfortunately, no one else on the team knew/remembered anything about state
machines, so my epiphany didn't help them out any, even if they had had the
same kind of classical Comp Sci education as me.

Naturally, the first thing I did with this power was to leverage it into World
Domin... no wait, that was something else. :D What I did with this knowledge
was to hassle the people until they gave me a diagram of what the state
transitions (or whatever they called them in Business Analyst land) were
supposed to be, and then I went back and compared them, and they were not the
same :(

------
rdtsc
Erlang comes with gen_fsm behavior because often when writting network
protocols and servers, a state machine is a useful abstraction.

Relevant:

"Rage Against The Finite-State Machine" from "Learn you some Erlang For Great
Good"

<http://learnyousomeerlang.com/finite-state-machines>

~~~
teaspoon
In Haskell, you can represent a state machine and its current state using an
iteratee:

[http://www.yesodweb.com/blog/2010/09/enumerators-tutorial-
pa...](http://www.yesodweb.com/blog/2010/09/enumerators-tutorial-part-1)

An iteratee is essentially just a function that takes an input symbol and
returns either a final state value or another iteratee.

------
audionerd
So, more often than not, you'll catch your state machines attaching behavior
directly to your objects. Which sometimes bugs you, because you want your
states to be less about "nouns" and more about "verbs".

And eventually you notice that, in most cases, you crave coordination across
those "nouns" (e.g.: "a transition in model A provokes a transition in model
B"). The real workflow now lies "at the intersection of two models". You start
to wish for the equivalent of "process management" in addition to state
management.

So this, coupled with general unhappiness for the sort of anti-modular/anti-
abstraction problem you see in state machines, might incite you to look at
"workflow engines" like Ruote.

<http://ruote.rubyforge.org/>

TL;DR I am drinking the 'ruote' kool-aid right now. Augment your state
machines with a great coordinator in the sky, a few levels higher in the
architecture stack.

(BTW: I'm paraphrasing this argument from John Mettraux's "state machine !=
workflow engine" post, and Kenneth Kalmer's Ruote presentation from this year.
Really changed my thoughts on the matter recently.)

------
billybob
Using the state_machine gem in one of our Rails apps, which tracks a workflow
where items can be received, entered, reviewed, rejected, etc, helped me think
through the business process and map that to our code.

We also logged all the changes in state. In hindsight, I should have added a
"previous log entry" field to each log item, to make it easier to trace the
history of any given item. Like "find all the rejections, hop back one through
the log history and show me who created that item." If the rejection
references the creation's id, that's easy; otherwise it's a query using widget
ids and the date and sorting to get the most recent entry before the
rejection.

------
protomyth
It is interesting how few languages make state machines easily read when the
appear in code ("what's with all the ifs?").

~~~
6ren
You could use polymorphism - but that scatters the transition logic to the
four winds.

I guess pattern matching would work well (haven't used it that way myself).

An actual state transition table seems the most straightforward way to
represent it - but I agree, it's striking that there isn't native support for
it. Perhaps there isn't a better way to do it...?

 _EDIT_ just thinking, a state machine can be modeled as a regular expression
(they are formally equivalent). You could represent them as productions; or,
as regular expressions. Composed of the input symbols causing the transitions
- the states are implicit; but you could associate a function with each
symbol, by inserting it afterwards; the 'symbol' itself could be a function
that return true/false, for matches:

    
    
      isStart() setup() ( !isEnd() processInput() )* isEnd() teardown() | err()
    

I would guess that Lua deals with these problems a lot (as an embedded game
scripting engine, both enemy AI and UI logic might be modeled well by state
machines (in part) - perhaps it has a good way of handling them, or at least,
good idioms have developed.

~~~
shubber
Honestly, modeling state with polymorphism can be really elegant and powerful.
There are a few decisions to make (for instance, do States explicitly make
transitions happen, or do they return the next state?)

But in general, anywhere you see a lot of conditionals, you probably want to
consider a polymorphic approach. Especially if you have more than one function
with parallel logic trees.

~~~
6ren
What do you think of my concern of it "scattering the transition logic" across
the classes? Each class becomes a production, and only it knows which classes
can come next. It's hard to get an overall grasp of how the state machine
works, because you have to inspect all the classes to know the transitions.

This is a significant concern for me when reading others' code: the individual
parts might be easy to understand, but there is usually no documentation of
the overall design, of how the parts operate together. And there is no code
that ties together all the parts - so you are forced to inspect all the local
details in order to get a global overall view.

There are many ways to evaluate a program - how efficient it is, how many
features it has, how complete it is, whether it is consistent, whether it is
correct, how easy it is to prove things about... but I think how much work it
is to understand is one of the most important - and usually neglected. For a
complex program, having some way to quickly grasp the overall design is key to
this, IMHO.

------
signa11
this is why i like ragel (<http://www.complang.org/ragel>) a lot. seems that
zed-shaw also has used it in couple of his projects e.g. mongrel most notably.
would be particularly cool if ragel can be combined automagically for some
protocol parsing tasks...

~~~
shabble
I'm also a big fan of ragel, and have used it for various protocol
implementations. One of the really nice features is that you can have it
output graphviz dot files, to get an actual visualisation of your state
machine, so you know where you've missed a transition, or how you've
accidentally hit a state explosion with a bad rule.

------
pbsurf
Learning HDL (e.g., Verilog or VHDL) is a great way to force-feed yourself
state machines.

~~~
zwieback
Yes, or PLC (ladder logic) programs. That will put hair on your chest and give
you a real appreciation for the luxuries of high-level programming languages
running on top of a traditional processor.

------
aristidb
State machines are anti-modular.

State machines are anti-abstraction.

State machine code is hard to read.

~~~
forgotAgain
I disagree.

 _State machines are anti-modular_ : By clearly defining the transitions from
one state to another and when outputs can occur I see state machines as making
it easier to develop modular applications. I don't see how it inevitably leads
to non-modular code.

 _State machines are anti-abstraction_ : If you're modeling a process then
some things can't be abstracted. At some level you have to deal with real
world situations.

 _State machine code is hard to read_ : That's a function of the effort made
to make it easy to read. It's no different than any other situation.

In general I find state machine design to be helpful in literally controlling
the state of an application. By limiting what an application does and when it
can do it, via an easily understood mental model, it's a straight forward
design technique.

~~~
kreneskyp
The problem is that many apps are looking at the wrong states when they design
their machine.

For instance I worked on an app someone had build in which states were based
on a multi-page html form. When I added an android app allowing offline data
collection, I then had to hack around the state machine. We couldn't just
create a instance of the object with the final data, we had to write code that
replicated the submissions of the html form.

~~~
jbrechtel
This echos my experiences exactly. I've found little value in state machines
as a frequently used pattern. Abuses abound and I've also ran into the multi-
page-html-form-as-a-state-machine anti-pattern. It's horrid and should not be
done.

------
jpr
I skimmed the whole thing before realizing I had parsed the headline wrong.

~~~
dasil003
Kinda like foie gras right?

~~~
jpr
Yep :)

------
chrisjsmith
For any .Net people here, this is a great piece of kit:

<http://code.google.com/p/stateless/>

------
pnathan
This is not an interesting thought for someone who has a degree.

