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:
- Spare
- Installed
- 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.
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
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.
Given Your additions (more than 3 states, not all transitions are allowed), I would do the following:
- 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. - 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.
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!
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.
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.
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...
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.
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
来源:https://stackoverflow.com/questions/1966950/workflow-design-dilemma-state-machine-yes-or-no