views:

759

answers:

8

Hello, 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.

A: 

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.

Dmitri Nesteruk
Doesn't address my dilemma - do I create an ever-running workflow (read - a state machine workflow) for each item, or do I only use the sequential workflows for transitioning between states.
Aviad P.
A: 

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...

raoulsson
Assume I have more states, and that not all transitions are allowed... I'll update my question.
Aviad P.
A: 

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.

Scott McClenning
+2  A: 

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.

Dave
I agree. You can use interfaces and dependency injection techniques to make the model flexible as well.
Brandon Montgomery
Does this refer to the actual .NET workflow foundation? Or are you talking about workflows in the english dictionary meaning of the word? I'm interested strictly in the former, while it looks like it is the latter...
Aviad P.
Oh I'm sorry Aviad. You didn't explicitly mention .NET workflow foundation, so I assumed You were asking for general ways to realize Your project.
Dave
+3  A: 

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
Maurice
A workflow doesn't have to have an end. That's the theory of course, for example, even if items may end up in the recycle bin, they can still be restored, there's no final state for the item, barring total disintegration. - Also, I am, of course, using workflows for the transitions between states, that's a given, and would be regardless of whether I also include a state-machine or not.
Aviad P.
I think the potential problem with endless workflows is that you have to update your objects 'in place' if you want to change business logic. If you change your workflow, maybe that would affect things like your database schema for persisting the workflow, which might turn out to be painful.Maurice's answer sounds like a good way of trying to avoid that issue.
Tim Lovell-Smith
+1. Workflow foundation is simply not the appropriate technology for problem defined in the question. @Aviad: Yes "theoritically" workflows do not need to end. However WF has more specific goals than a theoritical workflow. It is specifically aimed at Business processes that do come to a logical end. It is designed to model in-progress __tasks__. It is certainly not designed to handle thousands of very long running workflows.
AnthonyWJones
@Aviad: You are right that a workflow never needs to end. No program has to end but most do and for a good reason as there is very little that needs to go on for eternity. Creating an ever running workflow is easy and with persistence might not even cost much resources. However programs tend to fail so you need something else that makes sure no workflow disappear unnoticed. That is yet another program. Keeping the data in a database and starting a workflow when something happens is much more appropriate and safe.
Maurice
+2  A: 

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!

Ralf
I want to get specific regarding the use of .NET Workflow Foundation. Are you recommending that I use a state machine workflow along, of course, with state transition workflows, but that I use my own persistence for the items (which include their state)? - Also, I never intended for the workflows to remain in memory, of course they would be persisted using a workflow persistence service, but the form in which they are persisted by the SqlPersistenceService is opaque to me, I can't query it or do anything except reload the workflow. They would however never reach a final state - is what I meant
Aviad P.
I haven't worked with the .NET Workflow Foundation yet, and I gues I never will. I am turning my back to another Workflow solution because too much of the stuff is opaque to me. Often you see the solution, but the framework will not let you implement it. But that's another topic. When you work with a framework, try to stick to it. Implement your process / workflow / state machine the way the framework suggests. everything else will cause problems. Maybe the workflow foundation isn't the right frame work for your app if it causes too many problems?
Ralf
btw: a workflow which never reaches a final state shouldn't be a problem for a workflow engine. I guess the limit is more the number of active workflows which seems to be quite static in your case...
Ralf
+1  A: 

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.

TToni
Thanks for all your input TToni, I am still not convinced that there's no place for perpetual (state-machine) workflows. The theory talks about that, and the implementation definitely supports that. However I am finding it hard to ignore all the hindrances a state-machine workflow would incur on my application... The dilemma is still in effect :-)
Aviad P.
Well that's what I talked about. If you want to use some kind of tool but can't find a straightforward way to make it work for you, you probably use the wrong tool. Or you have a very difficult or innovative problem at hand (which does not seem to be the case here). Good luck anyway. I'll be offline for a while now.
TToni
+4  A: 

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.

David Robbins
Very interesting! +1 for the insight, I'm currently looking into this.
Aviad P.