-
Notifications
You must be signed in to change notification settings - Fork 30
Home
Welcome to Objectflow. We believe creating workflows should be easy and shouldnt bog you down with needless infrastructure. Objectflow is designed to guide you into creating workflows that are decoupled from the rest of your code.
When you get a chance, checkout the example project at tkellogg/objectflow-example for an example using ASP.NET MVC and objectflow
In order to send an object through a workflow, the object must implement [[IStatefulObject|https://github.com/tkellogg/objectflow/wiki/Implementing-IStatefulObject]]
. This interface has two methods to coordinate workflows and states (GetStateId
and SetStateId
). Both state and workflow IDs can be any kind of object that has a meaningful implementation of Equals(object)
. Strings and integers work great, as do Guids and enums.
Workflows are just a series of steps tagged onto a workflow object. Create a workflow step with the Do
method.
var workflow = new StatefulWorkflow<SiteVisit>()
.Do(visit => visit.InitializeAndOpen());
This creates a workflow with a single step, formed by a lambda expression that calls a method on a SiteVisit object. This example isnt very useful because its just a complicated way to call visit.InitializeAndOpen()
.
Real world workflows are made up of actions performed by people and glued together by your computer system. For instance, your product manager might hand you a user story for this workflow:
- Office manager schedules a date for a site visit
- Field inspector drives to the site, opens the site visit from a smart phone
- Field inspector conducts the site visit, adding information, conducting training sessions, etc
- Field inspector signs finishes the meeting minutes and sends them to corporate headquarters for approval
- Office manager validates meeting minutes and approves them
- Accounting office sends the visited facility a bill and writes a check to the field officer for reimbursement
Notice that there isnt much computing going on. However, your program must keep track of the site visit status and information related to it. There is some validation between steps, but generally its just a lot of leg work to pull objects in and out of the database and refresh screens with data. In objectflow, we begin by hacking out a wire frame of this process:
var workflow = new StatefulWorkflow<SiteVisit>()
// Step 1
.Do((SiteVisit v, DateTime date) => v.Schedule(date)
// Momentarily persist and abandon this object to the database
.Yield("Scheduled")
// inspector is now ready to begin the meeting
.Do(v => v.InitializeAndOpen())
.Yield("Opened")
// Ok, inspector is ready to check out and get paid
.Do(v => v.PerformPreReleaseValidation())
.Yield("Pending Approval")
// manager clicks on an "Approve" button on the approvals screen
.Yield("Approved")
// Some closing routines before we close out
.Do(v => v.PrintInvoices())
.Do(v => PrintPaycheck(v.Inspector, v.VisitValue))
.Do(v => v.Close());
The new concept here is Yield
. It works just like yield works in C# when working with IEnumerable
. When we reach a Yield
, we pause execution of the workflow and store the state of the object. When the object resumes the workflow, it resumes from where it left off.
Starting an object through a workflow is usually as simple as calling the Start
method:
var visit = new SiteVisit();
workflow.Start(visit);
Of course, you might have noticed that our first workflow step actually took a DateTime
so we could set a scheduled date. We can just pass that date when we start:
var visit = new SiteVisit();
workflow.Start(visit, DateTime.Parse("11/11/2011"));
Oh yeah, and just simply starting a workflow without persisting it is kind of lame. Lets add a little persistence with our site visit repository:
var visit = new SiteVisit();
workflow.Start(visit, DateTime.Parse("11/11/2011"));
repository.Save(visit); // trust me, we created this guy earlier ;)
At this point you know how to create and interact with simple workflows. Please continue reading about Separating Concerns to find out how you can take advantage of some handy features of Objectflow.