我也在看powerstone workflow 的源码,今天竟找到一个工作流牛人的心得。爽!
转自:http://www.guodanpi.com/zblog/post/20.html
近几天一直在研究工作流,网上的资料也非常少,大多都是浅尝则止的要么用OSWorkflow做一个什么都不干的demo要么就是拼命的问shark、jBPM这类老外开发的东东,也都是问多答少,连问的问题都很浅显,感觉研究起来颇为费力。
工作流提得最多的是“工作流管理联盟(WfMC)的Workflow参考模型”,没看这个参考之前我就知道这个咚咚绝对是个超级sb,不然也不会吵吵嚷嚷这么多年都没个霸主出来。后来找到这个sb咚咚所说到的5大接口,pdf下下来几百页,别说本来就不懂,就算懂一点看这个也能研究要头发白,所以干脆就不管什么规范、什么接口,先看看工作流到底为什么需要,要实现哪些玩意才算能够交差再说。
中国人喜欢玩定义,所以工作流的定义那可真是五花八门,不知道写出这些定义的bb有没有真正开发过一个可用的工作流。看看这个感觉比较有意思http://blog.csdn.net/hongbo781202/archive/2004/09/26/117271.aspx,所以觉得他定义的是不是也能算数:工作流就是为了完成同一目标而相互衔接、自动进行的一系列业务活动或任务。
后来找到一篇介绍工作流的dbms实现的吹牛文章www.ict.ac.cn/xueshu/2001/061.doc,当然多少有点用处,它的组织结构、用户、角色定义这块按那幅数据库设计图来看还不错(打算借来改良我们现在的acl系统,呵呵),其他的糟粕不说也罢。
还是先理一理脑子里面的一些概念:(绝对是凭空设想,如果有和××规范或××实现相同的地方纯粹巧合)
1. 一个工作流应该由多个状态构成
既然总说工作流是“基于有限状态机”的,“有一系列的活动”,那么工作流在“流动”的过程中总要有歇脚的地方,歇下来的时候给当前的状态拍张照就形成了一个“工作流状态”。当然,在真实设计的过程中,肯定是人为先定义好这些状态,由多个状态(一个开始状态,多个中间和结束状态)构成一个工作流定义。工作流对应到数据库来说除了用个id来记录外,几乎没有任何必须的属性(当然加个name好认谁也不拦你)。关键在于它的儿子(工作流状态)难定义。
2. 工作流的状态定义
工作流状态是一个静止的概念,说白了可能就是一个字符串“通过”,“审批”等等,但是他要决定如何处理前置状态流向它的信息。
应该说工作流某一状态的入口是1…N,它的前置状态可以有多个(当然开始比较特殊,没有),前置状态经过一定的条件后方可到达当前的工作流状态,问题的核心不在于有多少个前置条件可以到达当前状态,而是这些前置条件在到达时的规则,这个规则当然是对于前置条件已经满足,在“汇流”到当前状态时会有一些处理动作:(由于网上很多介绍都有一些处理的规则,但是我希望能将这些规则具体分配到是流入的动作还是流出的动作)
1)对于前置条件的流入如何处理
a. 顺序:当然是对单一的流入口来说的了,没有什么特别
b. 与汇聚(可能也就是oa里的会签):详细来说就是必须满足所有的前置条件方能到达当前状态,很好解释,所有的前置条件都必须处理,所以在数据遗留(后面再说)的处理来说是最容易的。
c. 或汇聚:相对于与汇聚,或汇聚就是只要有一个前置条件通过则可以进入到当前的状态。可以考虑当前的常任理事国的反对机制,只要一个反对,就不能通过。而或汇聚则是只要一个前置条件满足了,就可以进入当前状态。
d. 投票:票数达到一定的百分比或数量就算通过。想想人大代表的产生就很容易理解投票机制。可以理解是或汇聚和与汇聚的一个补充。
除了a意外,其他3个都有数据遗留的问题(呵呵,自己发明的概念):当工作流满足定义的处理规则进入当前状态后,如何处理那些不满足条件的前置条件的数据?举个例子比较容易说明:
项目招标,需要甲、乙、丙的三个平级领导的签字才能通过,如下:
甲签字 ----|
乙签字 ----| ------------------à 通过
丙签字 ----|
分情况说明:
对于与汇聚:甲通过,乙通过,但是直到丙也通过则进入通过状态。如果复杂一点,丙退回的情况下,如何处理?此时甲、乙的通过情况应该保持不变,只记录丙的退回,然后做退回上一状态的动作。
对于或汇聚:甲通过则全通过,此时需要清理乙、丙的待审批数据,改变该数据的状态。如果复杂一点:丙退回!那么现在就全乱了套了,所以个人感觉,或汇聚状态下,只要一个通过则该状态需要锁定,其他分支将不能再处理。
对于投票:如果说需要2个人同意方通过,甲同意,乙同意,好说,通过。如果复杂一点:甲通过,乙退回,丙通过!如何处理?又乱了套了,所以也是个人感觉,在投票状态下,应该处于锁定状态,知道满足通过条件或者不通过条件,方可处理。实际上这种情况非常复杂,可以采取增加优先级的方法处理,也就是说列举各情况的优先级,然后按优先级最高的处理。
2)对于流出如何处理
a. 条件:需要满足一定的条件才能流出
b. 时间:在无人处理的情况下,是否采用超时处理
c. 还没想到,呵呵
3. 工作流的状态间行为定义
实际上记录静态的工作流状态没有意义,我们需要考虑的是记录从哪个状态到另一状态的“路程”。所以在这里要定义的是我们常常用到的“箭头”,也就是一个起点,一个终点的记录。
唐僧经常被问:施主从哪里来,要到哪里去?工作流状态就是“大唐”和“西天”,状态间行为则要回答这个问题,但是比起唐僧千篇一律的回答,状态间行为自然要复杂得多。
1) 解决从哪里来:
前面已经说明,我们要记录的是各状态间的“箭头”,由于对于这个“箭头”来说只存在唯一的起点和终点所以在数据库的设计上,“从哪里来”的信息(定义为FromState)。
2) 解决到哪里去:可以定义为ToState
可以看到状态与状态之间是不止一种状态间行为的。
我们可以大致定义数据库如下:
class Workflow{
Long id;
}
class State{
Long id;
Workflow workflow;
String fromCondition;
String toCondition;
}
class Route{
Long id;
State fromState;
State toState;
}
先想这么多,明天继续完善,呵呵(都是瞎扯啊)。