Using a state machine to enable a complex workflow process


Even a moderately complex workflow process can turn into a spaghetti nightmare using a graphical model.

Note: This is not intended to be a tutorial on state machines (google is your friend), nor a step by step how-to on implementing a state machine in your workflow system.  This is simply to introduce a concept for managing (and maintaining) complex workflow processes.

 

Most modern workflow engines (iProcess, Captaris/Teamplate, and BizFlow to name a few) provide a graphical tool with which to "draw" your workflow process.  This has several advantages:

  • Qucikly layout the rudimentary process
  • Short learning curve
  • Easy to show to others for validation/correction

But once the complexity of the model reaches a certain point, the graphical model breaks down, becomes more of a hindrance to understanding the workflow model than a help.  For example, here is a moderately complex workflow that shows how quickly a model can degenerate to something less than understandable:

 

 

I am quite sure the designer didn't intend for this to happen (who would?).  But as the model grew more complex, as the various exception handling was added, as various integrations with outside systems were created - it became... a big pile of yuck.

 

What I am going to describe below only makes sense for complex workflows.  So lets define what I mean by complex.  If you look at the diagram and after thirty minutes of study you really don't have a good grasp of what it is supposed to do - it's probably a good canidate for conversion to a state machine driven workflow.  State machine driven workflow graphic models tend to be pretty simple.   Here is another workflow model which is implemented as a state machine:

 

 

They contain all the same user and system tasks as the original workflow, but rather than handle the complex, conditional routing in the graphic definer, the routing and validation logic gets moved into code.  That code embodies a state machine.  Each user/system task represents a state.  So you have state in the statemachine for each user and/or system task.  Generally speaking the flow works in this manner:

 

  1. Routing takes the workflow though a validate task.  This task is responsible to ensure that the data set/modified by the current state is valid.  If the data fails validation, then an invalidData flag is set.
  2. Next the workflow routes to a process task.  This task is responsible for the routing to the next user or system task, this is done by updating the workflow variable that contains the current state.
    • If data validation has failed, the state is set so the flow gets routed to the appropriate task for handling exceptions.
    • If the workflow has reached it's final state, the state is set so the final system task is executed (often a task that archives audit trail and other workflow data)
  3. The next user/system task is executed (based on the state)
  4. Step 1 is repeated.

Both the validate and process tasks are usually coded as switch statements of some sort (depending on the underlying language).  

 

Here is another Accounts Payable workflow, implemented as a state machine.  NOTE: You can't tell what logic is implemented from the diagram, but the general flow should be obvious:

 

 

All tasks route back through the Validate and Process tasks.  Each link from the Process task to the the user and/or system tasks contains logic that only engages the task if the state matches the task name.  Since most workflow engines don't support state machines natively, you have to implement this logic in what ever fashion your workflow engine dictates.

 

Here is a small part of the Process task code for the state machine based workflow procedure diagram shown above

 


static public bool Process(ref EMCor2 thisModel, ProcessState ps, ValidateState vs)
        {
            bool rc = true;
            // If state is valid, move to the new state
            if (ValidateState.Valid == vs)
            {
                // Here is where we define the logic for each state transition.
                switch (ps)
                {
                   
                    case ProcessState.Initial:
                        if (thisModel.WFData.GetValue("WFData/SPY_DOCTYPE").ToUpper().Trim() == "STATEMENT")
                            stateMachineSupport.setProcessState(ref thisModel, ProcessState.STMTTRAK);
                        else
                            stateMachineSupport.setProcessState(ref thisModel, ProcessState.CASETRAK);
                        break;
                    case ProcessState.CASETRAK:
                        stateMachineSupport.setProcessState(ref thisModel, ProcessState.STMTTRAK);
                        break;
                    case ProcessState.STMTTRAK:
                        stateMachineSupport.setProcessState(ref thisModel, ProcessState.POISSUE);
                        break;
                    case ProcessState.POISSUE:
                        stateMachineSupport.setProcessState(ref thisModel, ProcessState.STATEMNT);

     

...

 

The validate task does not implement any routing logic.  It's purpose is simply to validate the data for the current state.  What these validations entail are specific to the problem domain and can entail database lookups, calculations based on current data, etc.

 

The process task on the other hand does not implement any data validation logic, instead it is concerned with determining the next state for the workflow.  This is often conditional based on data in the workflow combined with current state.  This is where all the logic of the workflow resides.

 

How does this help the complexity problem?  What happens at each state is clearly deliminated in code.  You can easily see by looking up the incoming state in the process task what is supposed to happen next.  This makes debugging MUCH quicker/easier than chasing down links with logic attached to them in graphic workflow diagram.

 

What I intended to show here, is that a graphical diagram isn't always the best solution for developing/managing/maintaining a complex workflow model - and that under the right conditions implementing a state machine can go a long way towards building a very robust workflow process.  One that is simple to debug, extend, and maintain.

 

One other salient fact:  One Workflow vendor's support staff reports that state machine implemented workflow processes generate 75% less support calls.  This is significant (do the math).

 

 

  • Currently 0.00/5
Rating: 0.00/5 (0 votes cast)

Share It!