February 7, 2011

Too Many States


No, I’m not agitating for Tasmania to have its statehood revoked. Instead I want simpler state machines in programming. I’m a fan of the model of programming where the core of the system is a state machine firing events on state transitions. Listeners on those events then perform actions, possibly changing the state themselves. It doesn’t fit every scenario, but it works well in those places it can be applied.

I’ve worked on a few such systems and a major determinant of eventual success is the complexity of the state machine. Sometimes this complexity is caused by the state machine encoding multiple state flows. The system would be simpler with a set of separate discrete state machines, each with a distinct main flow. I think software engineers can get obsessed with trying to find a single comprehensive solution to a problem. This can blind them to seeing a more understandable solution by breaking the system into smaller parts.

Below is a state diagram similar to one I saw recently at the start of a project (I have actually simplified it a little, removing domain specific states and transitions for anonymity).

This doesn’t look right to me. Multiple start and end states, a loop, and if a few more error states are added the diagram starts looking like a spiderweb. Diagrams which have allowed designers/developers to express their artistic side (I once saw one in the shape of a phone) are a good sign that there may be too many states. In this domain there are really three interlocking flows which have just been placed together. Each of the three flows represents the state of communication with a different external system. There is no need for them to be combined. It makes more sense to separate them. Looking at this, and with a bit of domain knowledge (just trust me), it can be equivalently expressed by the diagram below.

I think this is much better. It involves a few more states in total, but each individual flow is easier to understand. The domain object holding the current state now has three state variables rather than one. The state of the whole system is now the combination of these three state variables. This more accurately describes the current state and adds more flexibility for adding new states or transitions later. It is also possible to split the transition listeners into one for each flow, thus making them more focused events.

There are a few differences between the two state diagrams above. The three flows will have some interaction and the extra states are there to aid this. For example, the middle flow shouldn’t go to the Process state until either Enrich or Response Received has been reached. In the simplified diagram there are added Init and Pending states to act as placeholders while waiting for other events to occur. All three state variables start in the Init state, and as events occur they move on independently. The event that moves the middle flow on to Process is the event fired after one of the other flow’s transitions.

In 14 years how many times has decomposing a complex state diagram been beneficial on my projects? Three. Is it guaranteed to work? No. Will it work for you? Maybe. Think about it next time you find yourself staring at a complex state diagram.

comments powered by Disqus