State machines are one of those theoretical computer science concepts
that actually have a lot of use in the real world of writing working
code. In a state machine, you have a fixed set of states that the
software can be in, and well-defined transitions between states
triggered by events. I've used state machines myself in writing wizards,
for example: one state per wizard panel, with events triggered by
clicking the Next, Back, or Finish buttons.
The folks over at Desaware have taken the state machine idea and run
with it in producing their StateCoder product. The end result is a
framework on which you can build your own state machines quickly and
easily, and an excellent manual that shows possibilities far beyond that
of simple wizards. Imagine using state machines to manage long-running
operations with minimal UI impact, for example, or to deal with database
transactions. There's even a somewhat far-out example that shows how to
use a state machine in an otherwise stateless Web application to speed
up the user experience by predicting their future actions.
What you get here, besides the manual, is the Desaware.StateCoder
namespace. This namespace contains all the classes that you need to
define state machines and the messages and events associated with them.
Defining a state is as simple as inheriting from the State class, and
perhaps supplying an attribute to indicate that it's the first or last
The state machine itself is set up by inheriting from the StateMachine
class, with attributes to dictate which states it contains. Other code
tells it what message class to use, and when to start pumping messages.
Overall, it's quite straightforward to implement a state machine with
this code, and there are plenty of tutorials and samples to get you
There's a lot of depth here. State machines can be nested in other state
machines, for example. You can assign a state machine its own thread, or
support multiple state machines on a single thread. Almost anything can
be used as a message source, including timeouts and exceptions, as well
as arbitrary objects.
Yes, you could probably write your own state machine if you needed to.
But could you write one this flexible, one that's threadsafe for
background operation, one that's well-tested? And for less than the cost
of the product? When you see this common design pattern pop up, it's
worth remembering that Desaware got there before you.
Mike Gunderloy has been developing software for a quarter-century now, and writing about it for nearly as long. He walked away from a .NET development career in 2006 and has been a happy Rails user ever since. Mike blogs at A Fresh Cup.