2007年3月6日

如何在Windows Workflow Foundation(WF)选择工作流类型

Windows Workflow Foundation 支持三种基本的工作流模式:顺序工作流(Sequential), 状态机工作流(State Machine)和数据岛工作流(Data-Driven). 许多人都问我如何选择他们的问题,所以关于这点我愿意与大家分享一下我的看法。我们首先从一个简单的问题开始。有一篇文稿,我让弗雷德(Fled)来检查, 让乔尼(Joe)来审核,最后由我来把它发给我的客户。

这是一个显而易见的顺序工作流。为了实现我们问题,我创建了一个顺序工作流工程,分别增加了弗雷德检查,乔尼审核,最后我来把它发送到用户并完成工作流的顺序活动(Sequence Activity)。 一个顺序工作流的特点在于“工作流总是在控制之中”的事实。当弗雷德,乔尼和我被告知要做那些我们先前定义好的事情时,我们就开始做。我们做我们该做的事情,当我们已经做完了便通知工作流,然后由工作流来决定接下来发生什么。 当然顺序工作流并不意味着所有的事情都像上面我们描述的那样只在一条直线上发生,我们也同样可以有条件分支、循环等等。换句话说,就是

一个顺序工作流的特点在于“工作流总是在控制之中”的事实。当弗雷德,乔尼和我被告知要做那些我们先前定义好的事情时,我们就开始做。我们做我们该做的事情,当我们已经做完了便通知工作流,然后由工作流来决定接下来发生什么。

当然顺序工作流并不意味着所有的事情都像上面我们描述的那样只在一条直线上发生,我们也同样可以有条件分支、循环等等。换句话说,就是工作流控制着“顺序”。顺序工作流模式作为一个古典的工作流模式被许多工作流产品所支持和基于已经有很多年了。 依我看,给工作流一个不好的名字也是需要相当注意的。倒不是告诉人们该做什么有任何错误(有时候我也以自己的习惯行事),当有些时候这样确实是无法工作的。 让我们看一个另外一个例子。比如说我正在测试一个正在处于开发阶段的产品。当我发现一个问题,于是我新建了一个bug,并把它指派相应的开发人员,然后“安心地"等待程序员修复它。我将要写一个工作流来管理这个过程。到现在来说,一切听起来都很正常,步骤应该是:测试人员新建bug,开发人员修复bug,测试人员关闭bug。这就像我们刚才那个关于文稿的例子。 但这个方案是不牢靠的,测试的例子里真正的发生了什么呢?一个测试人员新建了一个bug,并且将它指派了比尔(Bill)。但是比尔说这不是我的问题,这应该是克莱夫(Clive)的问题,并且重新指派给了他;或者比尔说这根本就不是一个bug(或者类似说法),将其标识为不做处理;或者他要求测试人员给于更详细的信息;更甚者,他的心情很好,修复了bug并反馈给了测试人员;或者最初的测试人员有事不在,只有其他测试人员;或者测试人员撤销了这个错误的bug(不安全地)。每一个参与者都能做出一套不同选择在给定的位置上。 如果我以顺序工作流模式写这个例子会发生什么?可能会像这样(如果你能宽恕我这段伪代码): 。顺序工作流模式作为一个古典的工作流模式被许多工作流产品所支持和基于已经有很多年了。

依我看,给工作流一个不好的名字也是需要相当注意的。倒不是告诉人们该做什么有任何错误(有时候我也以自己的习惯行事),当有些时候这样确实是无法工作的。

让我们看一个另外一个例子。比如说我正在测试一个正在处于开发阶段的产品。当我发现一个问题,于是我新建了一个bug,并把它指派相应的开发人员,然后“安心地"等待程序员修复它。我将要写一个工作流来管理这个过程。到现在来说,一切听起来都很正常,步骤应该是:测试人员新建bug,开发人员修复bug,测试人员关闭bug。这就像我们刚才那个关于文稿的例子。

但这个方案是不牢靠的,究竟发生了什么呢?一个测试人员新建了一个bug,并且将它指派了比尔(Bill)。但是比尔说这不是我的问题,这应该是克莱夫(Clive)的问题,并且重新指派给了他;或者比尔说这根本就不是一个bug(或者类似说法),将其标识为不做处理;或者他要求测试人员给于更详细的信息;更甚者,他的心情很好,修复了bug并反馈给了测试人员;或者最初的测试人员有事不在,只有其他测试人员;或者测试人员撤销了这个错误的bug(不安全地)。每一个参与者都能做出一套不同选择在给定的位置上。

如果我以顺序工作流模式写这个例子会发生什么?可能会像这样(如果你能宽恕我这段伪代码):


         Tester T creates instance of bug workflow
         T adds bug details
         T assigns to developer D
LabelA: Switch
           D assigns to developer E
                 Goto LabelA
           D rejects bug to T:
                 Switch
                       T accepts rejection:
                       T updates bug and assigns to developer F:
                                Goto LabelA
                 End Switch
           D requests info from T:
           T submits info
                 Goto LabelA
           D submits solution to T:
           T withdraws bug:
         End Switch

你也学看出来了,出现在选择之内的循环和选择正在造成结构性的问题。(这里我捂着自己的鼻子使用了Goto,是为了让代码和设定的情形保持映射关系。)我们可以让这个例子更现实些,当有很多的bug接踵而来的时候,团队领导会把任务指派给团队中的人(或者是采取开发人员抢占的模式),并且增加了工程快照和设置bug优先级等方式等等,事情将会越来越糟糕。

这个例子引起的问题使用状态机模式是一个更好的方式。上面的伪代码变成了这样:

State: Initial
      Action: T adds bug details
      Action: T assigns to developer D; new state = Fixing

State: Fixing
      Action: D assigns to developer E
      Action: D rejects bug to T; new state = Rejected
      Action: D requests info;  new state = Pending Info
      Action: D submits solution; new state = Pending Approval
      Action: T withdraws bug; new state = Closed

State: Rejected
      Action: T accepts rejection; new state = Closed
      Action: T updates bug and assigns to developer F; new state = Fixing

State: Pending Info
      Action: T submits info; new state = Fixing

State:  Pending Approval
      Action: T rejects solution; new state = Fixing
      Action: T accepts solution; new state = Closed

State: Closed
这样是更清晰和更易于理解的,并且增加更多的特征也不会使整个结构变得复杂——仅仅是增加更多的状态机和动作。

实现这个状态机模式在Windows Workflow Foundation是非常简单的事情:只需要创建一个状态机工作流工程,然后定义状态机和所需要的动作即可。

评判使用状态机模式的标准是什么呢?简言之:是否重要的选择在工作流之外做出?(are the important choices being made outside the workflow?)是否用户在控制当中?(Is the user in control? )如果上面的答案是“是”,那么用顺序工作流模式想法去做会让任务一开始就陷入麻烦之中。从另一方面来说,那些选择在工作流之外的适合用状态机工作流模式。

如果工作流不要做任何选择,那那一种模式更适合呢?恩,一个状态机工作流控制了一整套选择,对于一个测试人员来说直到问题提交之后才接收到解决方案是没有意义的。这只有当bug工作流到达了适当的状态机活动——由大量的可能的分支,后才变得有效。

这是最后一点证明为何状态机工作流更适合这个bug程序。顺序工作流天生地,把所有可能的顺序行为编写到它的内部结构中去。但是在这,我们并不关心它。我们仅仅需要知道当前的状态,并且下一步可以做什么就够了,所以我们把时间花费到在进程中建模线路,尽管我们实际上也并不关心他们,并且那些线路是非常多的,就像在在这个bug程序一样多,所以通过顺序工作流模式能带来的好处不可避免地微乎其微了。


特别声明,文章翻译于http://blogs.msdn.com/davegreen/
版权由原作者所有。原文章关于Data-Driven类型的工作流的论述部分已被删节。

1 条评论:

匿名 说...

不错~~~