Creating a dynamic state machine with C# and NHibernate

In my last post (An architecture dilemma: Workflow Foundation or a hand rolled state machine?) I talked about the discussion around an architectural choice. The conclusion of that discussion was to hand-roll a dynamic state machine. This post is the first part of 3 explaining the solution we used. In this part we’ll focus on the state machine, in the following two parts we’ll be adding business rules to each state and utilizing a couple of tricks from NHibernate to make those rules rich.

If you are uncertain what the state machine pattern looks like, there is some information here: http://msdn.microsoft.com/en-us/magazine/cc301852.aspx . For the rest of this post I will assume that you got a basic understanding of it.

The requirements for our state machine was that users should be able to add their own states and tight them into the state machine. They should also be able to define the flow, designing the structure of which states can transition to each other.

The basic state machine looks something like this:

Classic State Machine

Since we need to be more dynamic then this our model turned out more like this instead:

image

In this model we are using composition instead of inheritance to build our state machine. The list “AllowedTransitions” contains a list of states that is allowed to transition to from the current one.

The method “CanBeChangedInto” takes a state object and compares it to the list of states and decides if the transition is allowed. For our scenario this comparison is done by implementing IEquatable and overriding the appropriate operators (==, !=).

This is defined on a template kind of entity, there will be “instances” made out of this template where all attributes are copied onto the instance.

The implementation of the ChangeStateTo method on the template is fairly simple:

Template:
public void ChangeStateTo(State newState)
{
    if (State.CanBeChangedInTo(newState))
        State = newState;
    else
        throw new InvalidStateTransitionException();
}

State:
public bool CanBeChangedInTo(State state)
{
    return AllowedTransitions.Contains(state);
}

Simple but yet very powerful and allows for the kind of dynamic state transitions our scenario requires.

Adding state transitions is easy as well, since the AllowedTransitions list holds

Our project uses NHibernate as a persistence engine and to persist our dynamic state we use a many to many bag mapped in xml:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="" namespace="">
  <class name="State" table="States">
    <id name="Id" type="int">
      <generator class="native" />
    </id>

    <property name="Name" length="255" not-null="true" />

    <bag name="AllowedTransitions" table="AllowedStateTransitions">
      <key column="FromState_Id" />
      <many-to-many column="ToState_Id"  class="State" />
    </bag>
  </class>
</hibernate-mapping>

Between NHibernate many-to-many mapping and the design of the state transition list it’s easy to start building an application upon this. We are not done yet though. Every state needs more transition rules then just “AllowedTransitions”. The next post will tackle that requirement.

Is Windows Communication Foundation to complex?

Today at ALT.NET’s unconference we had a great discussion initialized by Alan Smith about the state of WCF and the complexity, if any, it imposes on developers. The thesis was that WCF was hard to learn for the “Average developer” and there was a lot of underlying details of communication that might be too visual. Alan showed an example of all the details generated by SvcUtil in it’s default settings. He compared with ASMX web services where “regular” asp.net developers could develop new services as simple as they implemented an event handler.

My view on this is kind of simple and ties into discussions I’ve had in the past about The holy abstraction level, the real question to ask is if I and my project is ready for distribution? Am I skilled enough to wield a tool for building services?

ASMX is a bit simpler, sure, if you don’t want real security. Or are looking for reliable sessions or any other more interesting service conversation pattern then request/response over HTTP.

The simple truth is that anything but request / response has a lot of underlying principles that are far from easy. These principles is what WCF aims to be an abstraction layer for. Not HTTP request / response. Sure, there is a lot of things that can be simpler. More things that tools can do for you to make you faster. Some of the simpler conversation patterns could be easier to implement.

But the problem will still be the same, building distributed applications that scale, perform are reliable and secure is not a walk in the park. It requires skill, planning and a lot of thought.

Distributed applications are hard for a reason and no tool will make architecting them easy, any tool that try will fool developers into dangerous traps.

So in short, it’s not WCF that’s too complex, WCF takes complex conversation patterns to the average developer and that makes WCF seem complex at a first glimpse.

If you want to master WCF development, your first step should be to master distributed application design and conversation patterns. When you do; WCF will be an excellent and simple enough tool for you.

An architecture dilemma: Workflow Foundation or a hand rolled state machine?

Workflow Foundation is an interesting piece of technology, in a recent architectural decision for a project I had time to examine the pro’s and con’s of WF for a particular challenge.

This sprint a story came up that will give super-users of a system the ability to define new states in a state machine and attach business rules for state transition dynamically through a user interface. These custom states are then attached to entities in the system.

Workflow foundation is an excellent engine for this kind of flexibility, pop a couple of custom activities and just create new state machines for each time you need changes. Well, that’s what it says on the box, but is it really that simple?

On the execution side of things, WF is an excellent choice. Good engine with a lot of built in functionality. But what about the end user side? Allowing users to easily define new states, attach rules to each state and attach them to entity templates?

One thing that WF isn’t is User Friendly. So what would it take to make WF user friendly? A custom designer, that emits xoml, some training in the WF designer and process orientation and a container to run the state machine in. This is a lot of work.

WF is powerful, but when the user are involved. It’s weaknesses quickly become expensive.

A simple solution, not as powerful on the execution side, is to handcraft a state machine and store the state in a simple table or two. Utilizing the state machine pattern with a touch of strategy pattern and you can come a long long way.

So since the user experience was the top priority for our scenario and we really only needed the state machine functionality, no work to be done . The first iteration was handcrafted, utilizing NHibernate to store some state in a database.

So, WF does solve a lot of things. But it comes with a cost and increased complexity. If you aren’t using WF’s full potential, chances are it’s to expensive for you.

My next post on this subject will present the solution in code.