最近结束了一个企业OA系统的项目,客户是一家海洋航运行业的企业,散运业务全球第一。该系统以工作流系统为基础平台,对员工工作进行电子化和规范化,由系统来驱动员工自动、快捷、可管地完成日常工作。在开发过程中,在综合评比多种工作流产品之后,我们选择了开源工作流产品——OSworkflow作为底层工作流引擎支撑,通过扩展OSworkflow的接口把业务系统和工作流引擎完美无缝地集成在一起。本文就是跟大家一起分享osworkflow扩展过程中的经验心得,希望能对其他朋友有帮助。
在我们开发团队介入系统开发过程之前,这个项目已经完成了 quickstart 阶段,留给我们的阶段产品有:系统实现的proposal、一个能体现用户page flow的lo-fi,以及在mingle上的 story list和iteration原始计划。当然,还有项目团队跟客户形成的一个良好的互信基础和沟通渠道。于是,左 proposal,右 lo-fi,客户沟通在中间,我们就开始了系统设计的 inception。 inception阶段的目标根据不同项目会有不同。在这个系统里面,我们完成的目标有:确定系统实现使用的技术、针对技术进行spike探讨可行性、结合master story以及比较粗略的story list实现一个系统prototype。好,工作开始了!
为什么选择OSworkflow?
工作流系统其实在理论界已经是研究得非常成熟了,有 WfMC 组织来规范工作流定义语言,而且各种工作流引擎,不仅商业产品,像 JBPM、 OSworkflow、ofbiz等开源产品也都很多。这些产品都各有特点,应该如何选择呢?从使用率和文档完整度来看,JBPM 和 OSworkflow 占了上风,我们就从这两者里面选了。JBPM基于UML的状态图和活动图来定义流程,已经加入JBOSS大家庭,但是相对比较重。osworkflow是个非常轻量级的工作流产品,但是自从2006年就停止活动了。不管如何,选择的技术都是要为解决未来系统开发会面临的问题,才算是一个好的可行的选择。
通过分析quickstart阶段的proposal和lo-fi prototype,然后再反复跟客户确认,我们知道了客户在现阶段对系统的要求是:
- 只需要处理线性的工作流(未来可能需要增加对分支/合并的支持)
- 不需要功能复杂强大的工作流编辑器
- 节点流转主要是手工触发,不需要基于规则
- 需要能和遗留系统已有的工作流定义集成,而已有工作流定义用 osworkflow 定义
根据客户对系统的要求,我们选择了osworkflow作为最终的候选工作流引擎。因为我们对这几种工作流产品都不是很熟,对它们是否能满足系统要求答案不确定。而从另外一个方面来讲,如果系统足够简单,我们也可以自己实现一个状态机,自己实现对流程节点流转的维护。
为了做出选择,我们又分头对 osworkflow 的配置文件以及技术架构都进行了细致的研究。研究过程和结果就不细说了,网上有很多 OSworkflow 的介绍文章,大家可以参照。OSworkflow 会把一个简单的xml配置文件,转换成它定义的流程描述类(XXXDescriptor,我们也把它们称为osworkflow的models),然后在流转的过程中,将其转换成工作流实例和工作流节点,并通过相应的持久化接口持久化工作流的状态。整个过程用一个简图来表示,就会是:
图1 OSworkflow model
考虑到 OSworkflow 的实现也是非常轻量级,并且结构非常清晰,而且为了提供以后对分支/合并、以及自定义规则等流转形式的支持,我们还是选择了 OSworkflow,而不是自己去实现一个基于状态机的工作流引擎。但是,我们还不能直接把 OSworkflow 放进项目里面,然后直接引用:一方面我们不想让开发团队都纠缠于底层 OSworkflow 的技术细节,另外一方面也是因为 OSworkflow 并不能完全满足客户的系统要求。我们需要扩展!
为什么去扩展?
依然是问答模式,OSworkflow 有哪些方面不能满足我们系统的要求?
1. 系统对各个流程的定义都能有版本跟踪
客户会对流程定义进行修改,但是流程修改的过程中,流程应该继续按照原来的定义进行流转。这样,对于同一份流程,系统会同时存在两个不同的定义,并且都能正常流转。OSworkflow 基于XML文件的流程配置方式在这种情况下就不能满足。
2. 系统对流程定义的修改能实现“hot deploy”
客户对流程定义进行修改后,系统能自动提供给用户新的流程定义,而不需要重启服务器。因为 OSworkflow 是在系统启动的时候,将所有的流程定义都载入内存,在系统运行期不会去检测流程定义的修改。这样,OSworkflow 也不能满足。
3. 相对于系统的要求,OSworkflow 提供的功能还是太复杂了
因为 OSworkflow 是提供一个通用的工作流引擎,所以考虑了很多复杂的情况。这些复杂性对我们系统来讲,都是额外的不能对客户产生价值的特性,而且那些复杂性的存在,也会让我们开发的时候必须考虑到那些方面,从而影响我们的模型设计和开发。
除了上文提到的几个原因,我们考虑的因素还有很多方面,最终我们决定是在OSworkflow基础上进行扩展,来满足我们的要求。
如何进行扩展?
如何进行扩展?我们的原则是什么?没有一个清晰的目标,很可能最终扩展的方向和最终实现就会跟我们想要的目标离得比较远了。
原则一. DDD,MDA
我们希望开发团队在设计开发的过程中只需要考虑系统领域的模型,而不会 involve 到底层的流程流转细节。
“find core domain models”,我们重新研究了系统的 proposal 和 lo-fi prototype,找出系统里面的领域对象,它们之间存在这样的一个关系:
图2 系统model
从图1 OSworkflow model 关系图和图2 系统 model 关系图可以看出,它们两者还是存在着一定的相似点和不同点的。
相同点:
1. 相应 model 完成的功能和职责是非常类似的
2. 不同 model 之见的关系也是非常类似的
不同点:
1. model 的属性
2. model 的一些行为
原则二. decoupling
我们希望项目实现不依赖于某个工作流产品,而是可以很方便地迁移到其他的工作流产品。第一想法就是——“laying, isolate by interface”。
其实工作流产品除了工作流引擎负责流程节点流转之外,都另外包括这三部分:流程定义、定义解析和状态持久化。而成熟的工作流产品,不管是JBPM,还是 OSworkflow,都会提供接口进行隔离。在OSworkflow里面,接口WorkflowFactory会负责流程定义的解析和 OSworkflow models的初始化,接口WorkflowStore则负责将Workflow和WorkflowEntry的状态持久化。这样,我们就可以定制实现接口,将domain models转换成 OSworkflow models,在流程流转需要持久化流程状态的时候,则会去持久化domain models。
经过这样几个方面的论证和分析,得到的最终方案如下:
- 使用domain model,而不是工作流model
- 扩展接口将 domain model 转换成工作流 model
- 扩展接口提供自定义的工作流状态持久化
- 不改动 osworkflow 内核
最终实现
图3 系统实现图
我们得到了什么
- 使用 domain model 进行开发
- 底层工作流引擎对开发团队透明
- 设计、优化工作在应用层次来进行
(本博未来会以同一个项目为例对敏捷项目各个阶段过程进行简单的介绍,敬请期待)