tags:

views:

197

answers:

2

I'm in the process of designing a system that will allow me to represent broad-scope tasks as workflows, which expose their workitems via an IEnumerable method. The intention here is to use C#'s 'yield' mechanism to allow me to write psuedo-procedural code that the workflow execution system can execute as it sees fit.

For example, say I have a workflow that includes running a query on the database and sending an email alert if the query returns a certain result. This might be the workflow:

public override IEnumerable<WorkItem> Workflow() {
    // These would probably be injected from elsewhere
    var db = new DB();
    var emailServer = new EmailServer();

    // other workitems here

    var ci = new FindLowInventoryItems(db);
    yield return ci;

    if (ci.LowInventoryItems.Any()) {
        var email = new SendEmailToWarehouse("Inventory is low.", ci.LowInventoryItems);
        yield return email;
    }

    // other workitems here
}

CheckInventory and EmailWarehouse are objects deriving from WorkItem, which has an abstract Execute() method that the subclasses implement, encapsulating the behavior for those actions. The Execute() method gets called in the workflow framework - I have a WorkflowRunner class which enumerates the Workflow(), wraps pre- and post- events around the workitem, and calls Execute in between the events. This allows the consuming application to do whatever it needs in before or after workitems, including canceling, changing workitem properties, etc.

The benefit to all this, I think, is that I can express the core logic of a task in terms of the workitems responsible for getting the work done, and I can do it in a fairly straightforward, almost procedural way. Also because I'm using IEnumerable, and C#'s syntactic sugar that supports it, I can compose these workflows - like higher-level workflows that consume and manipulate sub-workflows. For example I wrote a simple workflow that just interleaves two child workflows together.

My question is this - does this sort of architecture seem reasonable, especially from a maintainability perspective? It seems to achieve several goals for me - self-documenting code (the workflow reads procedurally, so I know what will be executed in what steps), separation of concerns (finding low inventory items does not depend on sending email to the warehouse), etc. Also - are there any potential problems with this sort of architecture that I'm not seeing? Finally, has this been tried before - am I just re-discovering this?

+2  A: 

Personally, this would be a "buy before build" decision for me. I'd buy something before I'd write it.

I work for a company that's rather large and can be foolish with its money, so if you're writing this for yourself and can't buy something I'll retract the comment.

Here are a few random ideas:

I'd externalize the workflow into a configuration that I could read in on startup, maybe from a file or a database.

It'd look something like a finite state machine with states, transitions, events, and actions.

I'd want to be able to plug in different actions so I could customize different flows on the fly.

I'd want to be able to register different subscribers who would want to be notified when a particular event happened.

I wouldn't expect to see anything as hard-coded as that e-mail server. I'd rather encapsulate that into an EmailNotifier that I could plug into events that demanded it. What about a beeper notification? Or a cell phone? Blackberry? Same architecture, different notifier.

Do you want to include a handler for human interaction? All the workflows that I deal with are a mix of human and automated processing.

Do you anticipate wanting to connect to other systems, like databases, other apps, web services?

It's a tough problem. Good luck.

duffymo
This thing is going to have a very limited scope - it's for a personal project, so buying something is right out. I won't need post-build configuration of the workflow itself, though configuration of the workitems will be necessary. As far as things like email server, database, etc go - they're -...
Erik Forbes
... in there simply for the sake of example. I'm mostly trying to solve a problem that's modular in nature, but once I nail the workflow itself it won't be changed unless the requirements change. Human interaction is going to be limited to canceling or pausing the workflow as a whole, not -...
Erik Forbes
... having the workflow interact with a user through an interface or anything. As far as state machines go, I started with this sort of model, but then realized I was rewriting the wheel - C# uses a state machine when it compiles a method returning IEnumerable and the yield statement. That's -...
Erik Forbes
... how I came to this conclusion in the first place. Thanks for the input nonetheless, it's been helpful. =)
Erik Forbes
Oh - and to elaborate on the usage for this - it's for a piece of application automation software I'm working on that has a specific application and task that it's targeting.
Erik Forbes
Excellent, Erik, sounds like you have a good handle on the problem. Sorry I'm not more helpful.
duffymo
Not at all - thanks for answering. =)
Erik Forbes
A: 

@Erik: (Addressing a comment about the applicability of my answer.) If you enjoy the technical challenge of designing and building your own custom workflow system then my answer is not helpful. But if you are trying to solve a real-world WF problem with code that needs to be supported into the future then I recommend using the built-in WF system.

Workflow support is now part of the .Net framework and is called "Workflow Foundation (WF)". It is almost certainly easier to learn how to use the built-in library than to write one of your own, as duffymo pointed out in his "buy before build" comment.

Workflows are expressed in XAML and are supported by a designer in Visual Studio. There are three types of Workflows (from Wikipedia, link below)

  • Sequential Workflow (Typically Flow Chart based, progresses from one stage to next and does not step back)
  • State Machine Workflow (Progress from 'State' to 'State', these workflows are more complex and return to a previous point if required)
  • Rules-driven Workflow (Implemented based on Sequential/StateMachine workflow. The rules dictate the progress of the workflow)

Wikipedia: Windows Workflow Foundation

MSDN: Getting Started with Workflow Foundation (WF)

Tom A
Uhh what? How is this answering the question?
1800 INFORMATION
Erik opened his question with, "I'm in the process of designing a system that will allow me to represent broad-scope tasks as workflows". He then went into specifics on a homegrown WF solution. I pointed out that there is a built-in WF solution. That seems like a good answer to me,
Tom A
Aye - it's a valid answer, though not quite what I'm looking for. I'm not considering the use of WF (at least until WF4) at this time, for this project. I don't need the features it provides, and the home-grown system I've built is minimalistic, yet provides all the functionality I need.
Erik Forbes
I just wanted to know if it seemed like a stable and workable system over time - maintainability-wise.
Erik Forbes
@Erik. It looks like an elegant solution and, in isolation, that sounds maintainable. But if I were another person faced with maintaining it I might wonder why I was learning a custom WF technique rather than learning the "standard" WF technology that I could use elsewhere in my career.
Tom A