15
votes

I'm a beginner with WF, but I've read a book and done a lot of googling. I want to write an inventory management service. The inventory is made up of individual items which have a state:

  1. Spare
  2. Installed
  3. In-Repair

Items may spend months in each state, and there are thousands of items.

The question is, do I create a state machine workflow for all the different states? Or do I create workflows for transitioning between states?

If I understand correctly, if I create a single state machine workflow, then there will always be a workflow running for every item. This means thousands of ever-running workflows. Also, I need to be able to display a snapshot of the status of each item, so that means I have to somehow query all the workflows for the state they are currently in, or otherwise persist to a database after each state transition.

However, a state-machine workflow logically sounds like the right thing to do, hence my dilemma.

Please help me if you can :-)

Thanks!

Update:

Assume I have more states than the above 3, and that not all state transitions are possible.

Bounty Winner: Maurice - Thanks to everyone else for really helping me understand more about workflows, the MS workflow foundation, and other more lightweight alternatives. Unfortunately, there can only be one bounty winner, and Maurice's answer along with its comments helped me the most.

9
I'm no workflow wizard, but as an architect I would seriously question your approach to model inventory item states with a workflow engine. Or maybe I miss something. What do you use the workflows for? - TToni
The 'meat' of the workflows lies in the transition between states, where I need to validate my business logic. For example, when transitioning between Spare and Installed I need to make sure that the installation location is vacant first, then I have to change state, and then I have to notify logistics about the installation, etc. - Aviad P.
OK, so you need to execute some business logic when an item changes state. But I still don't see why you would use WF to do this. I assume you store the current state of each item in some database anyway. If you don't and there are other good reasons to use WF, then having one WF instance for each item looks like the better alternative to me. But if the state transitions of the WF only reflect the item state transitions, then you just end up storing the item state in a complicated way (as persistent WF instances instead of some database column). - TToni
What you're saying makes sense, but then can you think of anything that would make this scenario better suited for a state-machine workflow? - Also, using a workflow (state machine or otherwise) is a good practice in and of itself, it makes the flow of execution much more clear. By not using a state machine workflow, some of the process is obscured in code. That's part of my dilemma. --- Good night TToni :-) - Aviad P.
I still don't feel that WF instances are the right tool to capture your inventory item states. If you have non-trivial logic that you want to capture in a WF for item state transitions, that's fine, but why not use a different WF for each transition, instead of one big WF that includes the inventory item states? You can still use a process model diagram to explain your overall logic, but you don't have to capture everything in a WF model. If someone runs into problems like yours then it's 99/100 times an indicator of using a component in a way it's not meant for. - TToni

9 Answers

22
votes

A state machine is a very powerful technique to implement, although I would recommend that you consider a framework called StateLess by Nicholas Blumhardt (Autofaq creator), as it is an amazingly simple implementation of a state machine that avoids the unnecessary complexity of Windows Workflow. His approach avoids the issue of long running workflows being held by a runtime engine, as the state is defined by a simple variable such as a string or int.

Here is a sample state machine:

var phoneCall = new StateMachine<State, Trigger>(State.OffHook);

phoneCall.Configure(State.OffHook)
    .Permit(Trigger.CallDialed, State.Ringing);

phoneCall.Configure(State.Ringing)
    .Permit(Trigger.HungUp, State.OffHook)
    .Permit(Trigger.CallConnected, State.Connected);

phoneCall.Configure(State.Connected)
    .OnEntry(() => StartCallTimer())
    .OnExit(() => StopCallTimer())
    .Permit(Trigger.LeftMessage, State.OffHook)
    .Permit(Trigger.HungUp, State.OffHook)
    .Permit(Trigger.PlacedOnHold, State.OnHold);

// ...

phoneCall.Fire(Trigger.CallDialled);
Assert.AreEqual(State.Ringing, phoneCall.State);

Your state can be an integer which will allow you to feed it the current state from a database. This can be set on the constructor of the state machine as follows:

var stateMachine = new StateMachine<State, Trigger>(
    () => myState.Value,
    s => myState.Value = s);

You can implement this in just one assembly, compared to the multiple projects you need to run Windows Workflow. Maintenance is extremely low, their is no "designer" that generates code for your, etc. Again, it is simple, and there lies the beauty.

9
votes

Not sure if a workflow is what you are looking for in the first place.

A workflow is some kind of business process that takes place. This implies a beginning and an end to the process. Your description sounds more like you are tracking an inventory of sorts with items that stay in the inventory.

A workflow sound more appropriate when an item changes state. For example when an item is installed and breaks down and needs to be fixed you would start a workflow to get the part replaced by a a working one, send the broken part to be fixed and in the end have it back at the warehouse as a fixed spare. The workflow would describe this process and start with the report of an item being broken and end with the item being either repaired or discarded and replaced.

This last workflow could very well be a state worklfow as the item goes through various stages like:

  • Broken and installed
  • Broken and replaced
  • In the shop for repair
  • Repaired
  • etc
2
votes

Given Your additions (more than 3 states, not all transitions are allowed), I would do the following:

  1. Store each item's state in the item itself.
    This can be achieved very easily: Add a member to a class or a column to a table etc., as others already mentioned in their posts/comments.
  2. Use one state machine (this can be anything from an instance of a class to a table with legal transitions), that holds your business logic, that is, the allowed transitions between states and the knowledge about what additional actions to perform, when an item changes its state.

All you need to do then is to transform Your items using the state machine, whenever an extern event occurs, that forces/implies just that.

2
votes

ok. let's see if I can help you. Let's start with the design:

it makes sense to design a state machine AND a Workflow. Both are just different views on your problem and shed some light from a different perspective on it. In fact, it often happens that a developer which is new to workflows designs a state machine instead of a workflow process. The workflow process view mainly switches the roles of the boxes and transitions in the diagram: a box is an activity which can change a state - on a transition, a workitem can get into a new state (ok, thats not scientifically correct, but it might help :-)

For me it seems that the state machine aspect is more important. So implement your software as a state machine.

And yes - you should make all items persistent in a database. That's how you also keep very long running workflows running - they live in the database until they get reactivated by any activity. That's how all off the shelve Business Process Management Systems (BPMS) do it. Those workflows are NOT kept in memory.

Keeping everything in the database will make it easy to create reports.

As other already have mentioned, create a new colum with the state information or even create a new table with meta data: state, maybe a log when the state has changed, who changed the state, infos about upcoming events (a part has been ordered but not delivered - after how many days should someone check with the supplier if the delivery has been lost?). This will give you the opportunity to add meta data as needed without affecting your parts database.

Hope that Helps!

1
votes

As discussed in the comments to the original post I have some issues with using WF for this particular problem at all.

The sentence "Items may spend months in each state, and there are thousands of items" is the trigger for this: I believe that workflows (modeled with WF) should be shorter lived. While there is no hard rule as to how long a WF instance can or should live, several months or maybe even years triggers kind of an "out-of-bounds" exception with me, especially when this would be a very common state of affairs for thousands of items :-)

The reasons for using WF in your comments are sound, but don't address this particular point. So I would advise you to use shorter lived, specialized WF models for the things that happen between inventory item states, but don't capture the item state itself in a WF state. Long lived, seldom changed states are more suited to a database engine, where people expect them to be and where they are easily reported upon.

0
votes

Even though the state-machine pattern is technically the correct option, there's also an option to create a sequential workflow with one giant loop. In some cases, it actually works better and is more understandable.

0
votes

You have three distinct states and as far as I can see, all transitions are allowed. Given that, I would not bother about a state-machine in the sense of a piece of code that checks the allowed transitions and does the moving forward.

State machines make sense when the states drive the business or when there needs to be a trusted single piece of code that is the sole actor in charge of "validated transitioning".

Put more simply, you just need the entities with a given state at any point in time...

0
votes

Aviad, I agree with your comment that the workflow should be between states. The states of the parts being inventoried sounds like a status/property of the item. That status can be stored in nearly any manner (e.g. database, file...) because the movement of the item between states would live in the business logic layer.

Sounds like a fun project, good luck.

0
votes

I think we need to understand couple of things here.

State Machines - Will focus on representing a particular state your entity is in.

WorkFlow - Will define the processes you are following for moving your entity from initial state to final state.

In your case as your overall process is revolving around a single entity and its current status at any given point of time is singleton, I would recommend to go for a state machine.

Recommendation: Apache Commons SCXML provides a lightweight, embeddable state machine engine which can easily be configured and customized at runtime within your application.

Key point here is you have to define your scxml in such a way that between the state transitions of your entity - You can specify the workflows you want to perform using 'actions' or 'listeners'.

SAMPLE PROGROM: https://www.javacodegeeks.com/2012/06/apache-commons-scxml-finite-state.html

MORE ABOUT Commons SCXML 2.0 https://events.linuxfoundation.org/sites/events/files/slides/ApacheConUS2014%20-%20Apache%20Commons%20SCXML%202.0.pdf