没有进一步总结工作流领域模型,还基本停留在第一版的层次上,导致:
层次不甚清楚
增加新功能困难
事务脚本过多,带来重复代码
组件职责相对混乱,尤其是服务组件与其它模块耦合太多,应更清晰的定义一个内核服务层
没有做并发设计,导致:
性能低下
存在死锁可能
二、Design Principles 针对接口编程与控制反转整个系统针对接口编程,降低了编译时依赖;利用IoC,通过配置来组装系统,定制运行时行为;带来的最大好处就是,我们获得了一个可在分布式和嵌入式之间通过配置切换的引擎,不需要修改源代码,大大提高了持续集成的方便性和速度,提高了适用性
三、Architecture Patterns 1、分层(POSA1)通用类库:供所有其它层调用
内核服务层:供内核调用
内核:独立运行或作为普通类库被调用
内核开发包:开发外围服务时使用
外围服务:与内核一起运行,供应用开发包调用
应用开发包:开发具体应用时使用
具体应用:调用应用开发包来与系统交互
其中,内核中的工作流领域模型又分三层
语法层:负责将流程定义的文本形式转化为内存对象
语义层:负责将这些内存对象无意义的扩展属性解释为有意义的模型属性
实例层:表示运行期的语义层对象,其中各个属性使用运行期实际的值来实例化
2、微内核(POSA1)内核服务层+内核,完成了最基本的工作流引擎,如实例化流程并调度之,产生任务表,处理消息请求等;
外围服务则提供了做为一个产品化的工作流引擎所必备的特性,如持久化,超时处理,任务通知,查询接口,命令接口等
外围服务以插件的形式配置到系统中
四,Design Patterns 1、领域模型(PEAA)+Visitor(GoF)+事务脚本(PEAA)+命令处理器(POSA1,GoF) Problem:P1:目前对工作流领域模型了解的不够透彻,而开发过程中需要不断增加目前的模型不能直接支持的功能,如撤回、回退等
P2:如果坚持使用领域模型,则增加一个功能基本对应着为领域对象增加相应的方法,则同时增加多个功能时,增加了并行开发和版本控制的难度,降低了开发效率
Constraint:C1:需要在不修改领域模型的情况下动态增加功能
C2:需要在不修改领域模型的情况下动态为客户端提供新功能调用接口
Solution:S1:使用“领域模型(PEAA)”为当前所了解的工作流领域建模,支持基本功能
S2:使用“Visitor(GoF)”为领域模型动态添加功能,这些功能通常还不是很清晰,需要迭代开发,逐渐合并到领域模型中
S3:使用消息对象为客户端动态的添加调用接口,使用“命令处理器(POSA1,GoF)”为服务端动态的增加相应的处理接口
S4:命令处理器的执行体则是“事务脚本(PEAA)”,它调用领域对象的方法,或“Visit”领域对象来完成功能;目前这一部分存在重复代码,需要进一步弱化或减少事务脚本,丰满领域模型;另一种方案就是“元工作流”,即工作流系统中的事务脚本也用工作流来实现,困难在于抽象出一个工作流的元层次
2、主动对象(POSA2)+异步完成标志(POSA2)用于自动型活动;自动型活动在自己的线程中独立、主动的运行,从引擎传入的异步完成标志中获取参数,执行完毕后将结果填写到异步完成标志中,并向引擎发送完成消息,以使“堵塞”的流程继续运行(此处的“堵塞”并不是真的堵塞,而是当自动型活动对流程来说必须是同步完成的时候,流程的一种无所事事的状态);这里更像是“收集参数(TDD)”模式,而不是异步完成标志
3、反应器(POSA2)+监听器用于将内核事件发送给外围服务,实际上是一种手工AOP实现,下一版可将目前手工触发事件的地方重构为pointcuts,将监听器重构为advisors
4、插件(PEAA)用于将外围服务动态配置到系统中
5、查询对象(PEAA)就是前一版的“通用查询接口”,这一版用“Generic + Functional Programming”重构了一下;目前系统中所有的查询条件都是通过查询对象来设置和获取的,问题时效率较低 6、包装器外观(POSA2)
用于对Xml、消息系统等外部资源的访问,在将系统从.Net平台移植到J2EE平台时,该模式发挥了巨大作用,大大缩短了移植时间
See Also:
《工作流:第一次发版,设计总结》
本文地址:http://com.8s8s.com/it/it32515.htm