【翻译习作】 Windows Workflow Foundation程序开发-第一章01

时间:2023-02-01 17:24:19

第 1 章    欢迎来到工作流的世界

…思想如蝴蝶般飞到我身边 —— Gossard / Vedder

(译注:Gossard与Vedder是来自Pearl Jam乐队的2名乐手,该句出自他们的歌曲《Even flow》)

Windows Workflow可被看作是继COM+和分布式事务协调器(DTC)之后,Windows平台上最令人瞩目的一款中间件产品。它们之间的区别在于:不是每一个软件应用都需要进行分布式事务处理;但几乎每个软件都要在其内部实现工作流。为了能够领会微软设计Windows Workflow的初衷,让我们先从通常意义上的工作流谈起。

工作流是什么?简单地说,一个工作流就是为了完成一个特定任务而涉及的一系列步骤、决策和规则。想一想你在当地一家比萨饼店点餐这样一个流程。你先跟餐厅招待讲明想要哪款比萨饼。招待把点菜单传给厨师,厨师就着手把原料处理好并放入烤炉。稍后,厨师把烤好的比萨饼交给招待,招待把比萨送到你面前并跟你结账。至此,整个流程结束。这项工作先“流”向招待,然后“流”向厨师,最后又“流”了回来。

在上述每一个步骤中,所有参与者都进行了规则评估并做出决策。厨师在接受点菜单之前要先看看后厨的备料是否够用。在结账时,要是你拿出了优惠券,招待必定要看看它们是否有效;如果怀疑你用假钞付款,他还要通知餐厅经理。

工作流不一定非要有人参与其中(这点好啊,因为人可是有本事把最简单的过程都给搞复杂了)。一个工作流可能发生在两个分布式应用软件之间。例如,两个内容管理软件可能会在夜间通过应用一系列特定的操作和规则来实现二者间的内容同步。

大部分的工作流都是有状态的,而且经常会需要相当长的执行时间。幸运的是,你点的比萨饼会在30分钟内做好。在这段时间内,点菜单的状态信息,比如你已经点的比萨饼盖头,不能有变化。比萨饼店向供货商定奶酪的流程可跟你点比萨饼的不一样。供货商不可能在30个小时内都不把奶酪送来,比萨店也不会在30天内都不向供货商支付货款。在那30天中,对于一个交易来说,需要某种东西来维持其工作流状态。

一个工作流在其生存期内可能要花费大部分的时间等待来自外部世界的事件信息。在顾客等待上菜,招待等待顾客付款,或者厨师等待比萨出炉的时候,工作流会处于空闲状态。在这种情况下,工作流并不需要任何资源。

一个工作流就是为了完成一项任务而执行的一系列步骤。工作流经常会长时间地运行,而且它是有状态的,时常需要等待事件,并与人进行交互。你会发现工作流无处不在。作为程序员,我们经常要在自己开发的软件中实现工作流。

1.1         创建工作流解决方案

我们都有参与一些软件开发项目的经验,启动这些项目的目的就是想通过软件来改进现有的业务流程。这些流程可能是关于比萨饼订单的,关于金融交易的,或者是关于医疗保健的。无论如何,每当谈论到这些项目时,我们都不可避免的要碰到“工作流”这个老朋友。工作流看似简单,可是深入其中,你就会发现内藏的玄机。为了管理工作流状态,我们需要数据库表格和数据访问类。我们需要Email发送组件和队列消息等待组件。我们还要告诉计算机如何执行工作流。让我们先来看看理论上工作流是如何实现的:

// 这是一个处理新提交的采购订单的工作流
class PurchaseOrderWorkflow
{
public void Execute(PurchaseOrder order)
{
WaitForManagerApproval(order); NotifyPurchaseManager(order); WaitForGoods(order);
}

}

假设我们已经给出了Execute当中三个方法的定义,一个工作流看上去真的会如此简单吗?答案显然是否定的。我们必须要编写一些代码来实现异常处理、日志记录和诊断功能。我们需要引发事件并提供挂钩函数以便能够跟踪和取消正在运行的工作流。同时,这个工作流会在大部分时间里处于空闲状态并等待一个外部事件发生,比如说一直在等待供货商把已下单的货物送上门来。在等待到货的时候,我们不能让运行中的应用程序线程空空等上几天甚至几周。我们需要提供一种机制,它能够把工作流的执行状态保存到持久化的数据存储介质中,然后将这个正在运行的工作流实例从内存中清除。当有一个重要的事件发生了,我们还会恢复这个工作流的状态,并让它继续执行下去。

遗憾的是,这样一来,我们就会在工作流内部和外部添加太多的代码,以至于使自己迷失在工作流之中,颇有一种“不识庐山真面目,只缘身在此山中”的困惑。所有这些支持性代码会掩盖住我们正试图实现的业务流程。一个不懂技术的业务人员将永远无法透过这些代码看清其中的工作流。一个程序员如果不对代码仔细探查一番,也不会理清其中的工作流。

一种改进的工作流设计方法试图把工作流的定义与执行该工作流的引擎和支持性代码相分离。这种方法允许程序员,甚至是业务人员,来描述这个工作流 “应该做什么”,而让工作流引擎来决定“如何”让这个工作流去做。目前,许多工作流解决方案都是在广受欢迎的尖括号中定义工作流。让我们看看理论上使用XML定义工作流的方法。

<Workflow Name="PurchaseOrderWorkflow">
<Steps>
<WaitForTask Event="ManagerApproval"/>
<NotifyTask Target="PurchaseManager"/>
<WaitForTask Event="Delivery"/>
</Steps>
<Parameters>
<Parameter Type="PurchaseOrder" Name="order"/>
</Parameters>
</Workflow>

这里再问一句,一个工作流看上去真的会如此简单吗?这次的答案是肯定的;我们还需要一个能够理解这段XML并把它翻译成计算机指令的工作流引擎。这个引擎将包括所有必需的功能,比如异常处理、追踪以及取消执行功能。

 【翻译习作】 Windows Workflow Foundation程序开发-第一章01

我们在前面看到的C#代码是一个命令性编程方式的例子。在这种方式中,我们通过提供一系列可执行的指令来描述“如何”完成一项任务。上面的XML标记是一个声明性编程方式的例子。在这种方式中,我们对任务看上去是“什么”样子进行描述,而让其它软件来决定为了完成任务需要执行哪些步骤。软件市场上大部分的商业化工作流解决方案都允许使用声明方式定义工作流,因为这种方式不与异常处理、事件激发等低层次的实现细节搅合在一起。

使用XML的好处之一就是有大量的工具能够对XML标记码进行读取、修改、创建以及转换操作。也就是说,我们可以借助工具进行XML开发。与解析C#代码相比,XML标记码解析起来更容易,并且可以使用图形框和箭头为工作流生成可视化效果。反过来,我们也可以先让业务用户使用可视化设计器,通过把一些图形框相连的方式绘制出工作流框图,再从框图中自动生成XML标记码。

我们到底想从一个工作流解决方案中获得什么?我们想以声明方式对工作流进行描述,也许还需要一个可视化设计器来帮忙。我们想把工作流的定义输入到一个工作流引擎中。这个引擎会运行工作流,并对错误、事件、追踪、启用以及停用操作进行管理。

下面该Windows Workflow Foundation登场了。

章节链接:
【翻译习作】 Windows Workflow Foundation程序开发

【翻译习作】 Windows Workflow Foundation程序开发-前言