《WF编程》系列之1 - Hello,Workflow & 创建工作流解决方案
5 min read

《WF编程》系列之1 - Hello,Workflow & 创建工作流解决方案

1. Hello,Workflow

什么是工作流?有一个简单的定义:工作流是完成特定任务所需的一系列步骤,决策和规则.

举一个现实生活中的例子,在饭店里,我们告诉服务员想要的菜,服务员记录然后交给厨师,厨师把做好的饭菜递给服务员,服务员再端给我们.

这个工作流的步骤是:我们(食客) > 服务员 >厨师 > 服务员 > 食客.

工作流的每一个步骤中都包含着制定决策.还是上面的例子,厨师必须比较服务员拿来的订单和库存的食材,而服务员则必须检查我们出示的优惠卷和钞票.

当然,并不是每个工作流都需要人类参与(人类会把最简单的过程变得很复杂).工作流可以在两个分布式软件之间进行.例如,两个内容管理程序在同步内容的时候或许需要遵循一组特定的步骤和规则.

大多数工作流都被状态化,并且经常运行相当长的时间.就像我们点的菜可能半小时后才被送上,在这半小时里,订单的状态信息必须保持有效.蔬菜供应商也许在30小时之后才能提供蔬菜,饭店也有可能在30天之后才能和蔬菜供应商结算.在这30天里,一些信息必须维持其状态直到结算为止.

如上所述, 也许工作流耗费了大部分时间来等待事件发生.但是当工作流在等待时,它是空闲的并且不需要任何资源.

最后再来归纳一下,工作流,是为了完成任务的一系列步骤.工作流经常长时间运行并且状态化.经常需要等待事件并且与人类交互.你可以在世界的任何角落看到工作流,作为软件开发人员的我们经常会为身边的流程编写工作流应用软件.

1.1 创建工作流解决方案

我们都从事改善业务流程的软件项目,无论这些业务涉及到外卖订单,金融交易或者卫生保健等等,谈论这些项目的时候,总是会出现一个词:工作流.

工作流听起来可能很简单,但是恐怖东西往往会在你深究之后出现:我们需要数据库和数据访问类来管理工作流状态;我们需要组件来发送E-mail或等待队列里的消息到达;我们还需要让计算机识别并运行工作流.理论上工作流是这样实现的:

// 最近提交的订单工作流
class PurchaseOrderWorkflow
{
public void Execute(PurchaseOrder order)
{
WaitForManagerApproval(order);
NotifyPurchaseManager(order);
WaitForGoods(order);
}
}

假定我们为这三个方法都定义了内部实现,那么工作流真的就这么简单吗?

答案是”NO!”.

我们还需要为异常处理和日志等等添加代码,还需要去触发事件,提供钩子(Hook)来跟踪并取消正在运行的工作流.有时候,工作流会变成空闲状态并等待外部事件的发生,就像你在淘宝购买的货物终于到了,虽然等了很久.但我们不能把一个正在运行的应用程序线程挂起来数日或数周来等待交付.我们需要提供这样一个机制:可以把工作流的执行状态保存到持久的数据库中,然后从内存中删除工作流实例,当等待的事件发生后,恢复工作流状态并继续执行.

不幸的是,围绕工作流将会有大量的代码,以至于我们在代码中找啊找啊都找不到工作流本身.这些代码正式工作流模块化的杀手.一个外行可能永远都看不到被深深埋藏在代码中的工作流,就算是开发人员,也需要狠狠的掘”码”三尺才能找到内部的工作流.

一个改进的工作流设计模式将把工作流定义从引擎和执行工作流的代码中分离出来.这种方法让开发人员,甚至是外行都知道该如何表示工作流,而工作流引擎只需关心如何执行工作流.下面来看看理论上的工作流定义XML:

让我们再问同样的问题,工作流真的这么简单吗?

答案是”YES!”.

我们想要的工作流引擎应该具备这样的能力:理解XML,而且可以把XML转换为计算机指令.引擎还应该包含所有我们需要的功能,例如异常处理和允许取消工作流.

使用XML的好处是有大量的工具可以去读写并转换XML.相比处理C#代码,处理XML更加容易.我们可以让用户在一个可视化设计器中将块用线条连接起来,画出工作流图表,然后生成XML.

我们的解决方案中需要实现怎样的工作流?为了清晰明了的表示工作流,我们需要借助可视化设计器.将工作流定义内置到工作流引擎中,让引擎去管理错误,事件,跟踪,激活和反激活.

接下来,进入Windows Workflow Foundation吧.