My growing appreciation for State Machines

I remember the first time I learned about State Machines in my computer science classes. Actually, I don’t remember too many things about finite-state automa other than the fact that there were way too many mathematical models and UML diagrams in that class!

It wasn’t until I started working at ShoeDazzle last year that I was re-introduced to the pattern. Here we use the state_machine Ruby gem, which serves as a nice, simple library for Rails.

I’ve found state machines to be extremely useful and I’m surprised why I’ve never used them before (whether using an existing library or just writing one from scratch). Instead of keying off of objects, arrays, booleans or other data types/data structures to determine a certain action, we make use of states in our models. It makes things clean and consistent. In my PurchaseReturn model, for example, I could implement several states and transitions which clearly define before/after transitions along with their transition requirements

state_machine :initial => 'approved' do

  after_transition :to => 'received', :do => :process_receive
  after_transition :to => 'cancelled', :do => :process_canceled

  event :receive do
    transition :to => 'received', :from => 'approved', :if => :is_valid?
  event :cancel do
    transition :to => 'cancelled', :from => 'approved'

As you can see in this example, it’s pretty simple to implement. You have ‘states’ as strings then ‘events’ which cause transitions from one state to another. In my example model, it initially gets created in the ‘approved’ state and based on certain events can either transition to ‘received’ or to ‘cancelled’. Then I invoke certain methods based on which state I transition to. I can also have conditional checks before making a transition (e.g. is_valid?).

Not all data models will greatly benefit from creating state machines. However, I think I’ll be making more use of them – particularly in the design phase of data modeling. If anything it helps you think of all the different states a model can be in. And if you can think in that respect, then I think you can avoid a lot of issues and bugs that will surface from bad design.