对于当前的工作流应用来说,人工节点无疑扮演着一个非常重要的角色。因为无论是传统的协同办公系统还是越来越多的企业应用,都需要有人参与到具体的流程中来。这篇文章着重分析工作流应用中人工节点所涉及到的参与者模式以及与此关联的工作项模式,最后会提供部分的解决方案作为参考。先简单说说什么是人工节点。
人工节点的概念是与自动节点相对的。顾名思义,人工节点就是需要有人参与的节点,在实际流程中,它体现在产生由人完成的工作项以及由人决定一些决策变量,这些决策变量会对流程的运行产生影响(例如分支的选择等等)。自动节点则是由工作流引擎自己调用完成,不需要人的参与,通常是执行定制的业务操作。相比较而言,人工节点更多的应用在管理流程里,而自动节点更多的则是应用在企业业务流程里。
人工节点的职责有三个:第一是决定该节点的参与者;第二是根据参与者生成需要人来处理的工作项;最后是当工作项被参与者处理完毕时,它将继续触发流程的流转。参与者处理工作项时可以处理相应的业务和设置流程决策变量。
下面我们就按照这三个职责分别对人工节点所涉及到的参与者模式和工作项模式进行分析。
一、决定参与者模式
换句话说就是决定该节点的参与者,这里有两种模式:引擎自动获取和最终用户指定。
1.1 引擎自动获取
所谓引擎自动获取就是由引擎在运行期计算实际的节点参与者,不需要最终用户的参与。这个计算基于流程定义时对该节点参与者的定义。
(1)直接指定人员、部门或角色
这种情况最简单,也最直接,用户定义节点时直接在组织用户树里选定人员、部门或角色,然后在运行期根据定义执行与或者是或的运算。大多数的工作流引擎都支持这种模式。但很明显它也存在着很大的局限性,它是静态的,一旦流程定义完毕参与者也就跟着固定下来,运行期的任何变化都不会对参与者造成影响,一个很简单的需求,请假流程,节点的参与者需要是当前申请者的部门领导,因为申请者在定义期是不确定的,所以根本无法指定节点的参与者,所以这种模式远远满足不了用户稍微复杂一点的需求。
(2)调用用户定制的计算参与者代码
这种情况通常是由引擎提供一个接口或是父类,用户需要实现或是继承这个接口或父类,然后实现相应的方法。这个方法通常会传递进一个执行上下文的参数,用户代码通过这个上下文可以访问到当前流程实例的信息,例如当前节点状态,工作流变量等等,然后用户可以根据实际业务和当前流程实例信息进行逻辑计算,最后返回一个参与者的ID集合。对于上一个模式里提到的计算当前申请者部门领导的例子,这个模式实现起来非常简单,首先获得当前申请者ID,然后在根据这个ID找出该申请者部门再找出该部门领导即可。
实际流程运行到该节点就会调用用户自己定制的计算参与者的代码,方法返回的参与者ID即作为该节点的实际参与者。
这种模式对于工作流引擎的实现而言最为简单,因为它把最大的复杂性都抛给了用户,由用户代码来计算实际的参与者。实际上很多开源的工作流引擎采用的都是这种方式,例如JBPM。但是这种方式给用户带来最大灵活性的同时也带来了复杂和烦琐。特别是当面对一个数量巨大的流程需求时,为每一个流程的每一个人工节点都定义一个参与者计算类是让人头疼的。再加上现在强调业务的敏捷,业务里的改变要迅速反馈到流程的定义里,让最终用户来编写或修改这个参与者计算类不现实也不可能。补充一下,这也是用户在考虑采用开源的工作流引擎还是商业工作流引擎时需要着重考虑的一个方面。
(3)指定前续节点的参与者
实际上是用户在节点定义时指定参与者为前续某个节点的参与者,当流程运行到该节点,引擎会自动获取所指定的前续节点的参与者作为该节点的实际参与者。
这个模式实现起来并不困难,大多数商业工作流引擎都对该模式进行了支持。它能够满足用户的部分特定需求。
(4)更为复杂的情况
用户的需求永远是复杂的,引擎所要做得就是尽量降低这种复杂性,流程的变化要能够迅速跟上业务的变化。考虑下面两种稍微复杂一点但是又很常见的需求。需求一:参与者为当前申请者的部门领导且职位为副总;需求二:参与者需要是测试部的所有女同事。这两种需求模式1、3都不能满足,2可以,但是正如提到的那样,模式2可能会非常的烦琐,不能适应业务的敏捷。其实这里的复杂性主要体现在:1、这里的参与者可能是运行期决定的;2、参与者的限制条件可能非常多,而这些条件不是简单的部门、角色或职位所能描述的。
对于一般的工作流引擎而言,它们都会选择模式2的实现,让用户自己实现逻辑。实际在后面的部分解决方案里,我们会看到更为好一点的实现方式。
1.2 最终用户指定
运行期由最终用户来决定节点的参与者。这也是中国国情所独有的特色。这种模式最为常见的就是用户提交工作项时的提交页面,用户在该页面上选定下一节点(多数分支用户选定时)和下一节点的参与者。这种模式本身并不困难,问题在于在提交页面需要给用户提供一个参与者的选择范围,让用户进行选择。而关于这个选择范围,则又回到前面所提到的引擎自动获取的模式,这个范围同样是需要引擎计算的。于是又回到了刚刚讨论过的四种模式。
二、参与者执行模式
现在,已经获得了节点的参与者。引擎下一步将会根据这个参与者生成工作项,注意,这里的参与者可能是一个人,也可能会是一个人员范围(即多个人)。于是就产生了参与者的执行模式,也可以理解为工作项的生成模式。
2.1竞争参与
当有多个参与者参与这个节点时就会产生竞争参与这个模式。同样一个工作,A可以完成,B也可以完成,于是就产生竞争,谁先开始这项工作,就由谁负责完成该工作。
2.2顺序参与
多个参与者按照指定的顺序完成该工作项。A完成之后由B完成,B完成之后再交给C完成。
2.3同时参与
多个参与者同时对工作进行处理,所有参与者均完成后,流程继续向后流转。这个模式其实比较复杂,因为这里同时涉及到一个完成规则:是所有参与者均完成工作项后流程流转,还是有其他规则?例如完成2个工作项即可流转,完成80%的工作项即可流转。稍候会讨论到。
2.4负载均衡
这也是一个常见的需求。这项工作A和B都可以完成,但是A目前有10个待办工作项,B只有2个待办工作项。于是用户期望该工作交由B来完成。这里需要实现一个简单的负载均衡。其实这种情况只是智能决策的一种最简单的情况,所谓智能决策是指系统能够根据一定的指标(由数据分析,例如人员的处理效率,工作负载等等)和规则来决定该节点的参与者。
三、工作项完成模式
这个模式在参与者执行模式为同时参与时有效。在说到这个模式之前,先简单说说工作项可能存在的几种特殊状态,这些状态包括挂起、人工终止和委派。挂起就是工作项暂时停止执行,挂起会影响到流程的流转,会导致流程的挂起。人工终止则是人工手动改变该工作项的状态,使该工作项终止执行,这个人通常会是管理员。人工终止也会对流程流转产生影响,当除去该工作项之外的所有工作项都完成时,人工终止该工作项会触发流程的流转。委派就是将该工作项委派给他人完成,同时该工作项也就结束了。人工终止和委派是工作项结束的特殊状态。
3.1全部完成
当所有工作项都结束时触发节点的结束和流程的流转。
3.2完成规定的个数
节点定义时指定工作项必须完成的个数,当完成的工作项达到这个指定的个数时触发节点的结束和流程的流转。
3.3完成规定的百分比
节点定义时指定工作项必须完成的百分比,当完成的工作项占所有工作项的比例达到这个指定的百分比时触发节点的结束和流程的流转。
其实这里很明显的可以看出不管是所谓的参与者执行模式还是工作项完成模式不过都是一定的规则,既然是一定的规则那必然就限定了应用的灵活性,用户能否自定义规则?根据业务灵活地修改规则?规则引擎+DSL应该是一个不错的选择。