使用面向服务的体系结架构(SOA)的其中一大动力在于提升企业的敏捷度,并将不可避免的改变所带来的影响减到最小。这一般通过把经常改变和相当稳定的实现工件进行分离来完成。支持这种分离的常用方法是分解(decomposition)和封装(encapsulation)。SOA的分解导致服务的定义代表更稳定的工件,而业务流程则代表更经常变化的工件1。在一个典型的SOA实现中,服务不会经常改变,但是非常经常地被组合和重组来构建/修改企业的解决方案。
这种分解不会直接标明业务规则的位置——整体IT实现中另一个频繁改变组件。由于业务规则可能相当经常地改变的事实,其中一种被广泛采用的实践是将它们与业务流程关联起来——更加频繁地变化的SOA组件。这种方法的普及又得到了“许多实践者将业务规则当作更广义的业务流程管理(BMP)的一部分”这一事实的支持,往往把业务规则和业务流程捆绑在一起。结果,许多人把业务规则引擎和业务流程引擎当作业务流程/业务规则实现的两种相互竞争的技术。这是由于下列几种普遍的误解:
- 业务规则和业务流程有着相同的设计模型和实现模型
- 业务规则和业务流程提供相同的工件,并且能以同样的方式使用
在本文中,我们将概括业务规则和业务流程之间的相同点和不同点,并介绍关于在SOA实现中配置业务规则的一些指导方针,以及每种技术的适当用法。
业务规则
“业务规则描述在实现一个组织的目标时所应用到的操作、定义和约束。这些规则用来帮助组织去更好地达成目标,在委托方和代理方内部进行更好的沟通,以及在组织和有兴趣的第三方之间的更好沟通,更好地示范了法定义务的履行,操作更有效率,操作更好地自动化,在当前的实践中更好地执行分析,等等”2。业务规则可以被看作是业务实践的一个集合,定义实际的实现——业务逻辑。这种逻辑的实现经常可以通过使用专门的工具进行简化——业务规则语言和业务规则引擎。
规则语言是一种特定于领域的语言,包含定义业务规则的构造。这些构造可以根据业务需求而大相径庭。从文本描述(使用一种特定于规则的语言或者简单英语),到决策表或者决策树的使用,都有可能。在有些情况下,也可能以图形的形式确定使用规则流的那些业务规则的执行顺序。最后一种经常是导致业务流程和业务规则之间产生混淆的原因。虽然它们看起来类似,但是业务流程流定义的是可以跨许多不同且异构系统的服务的执行顺序。另一方面,业务规则流则受限于规则执行顺序的编制(orchestration)。
特定于领域的编程语言
“特定于领域的编程语言(DSL)是一种对特定的任务组特别有用的编程语言。这是相对于通用编程语言(GPL)如C、Java、C#等等而言的3。DSL一般专门针对特定的问题领域进行量身定做。因而它能精确地捕捉领域的语义。为了进一步简化它们的用法,DSL一般是高度声明式的,并描述需要发生什么,而不是如何完成(后者是语言实现者的责任)。由于这一点,DSL经常被当作(可执行的)规范,而不是编程语言。
特定的DSL的主要优点在于特定于领域的抽象和符号,以及有限制(或者相当集中)的表达功能。对于应用程序的有些类而言,使得DSL比GPL更具吸引力的原因有几个4:
更容易编程
因为它使用了一个更高级别的抽象,与问题领域密切结合,定义要实现的内容,而不是如何实现,相比于GPL实现,DSL程序一般来说更加精确(由于它与领域的密切结合),并且更容易实现和理解(不仅对于开发人员,对于领域专家们也是如此)。这一般会致使缩短开发时间,减少昂贵的维护成本。此外,DSL还有高级的数据处理(debagging)支持,允许直接在领域概念级别上分析和调试代码。
系统的重用
重用始终是改善新应用程序的实现和缩短开发周期的方法之一。虽然GPL通过使用标准的和特定于领域的库来促进重用,但是它们的实际用法还是取决于开发人员。另一方面,DSL强制重用被DSL实现使用的库。此外,由于DSL是为特别的问题领域而定义的,因此它们捕捉且因此重用特定的领域知识。
更容易验证
随着软件工程的发展,正规的代码验证在成功的开发中正扮演着重要的角色。而对GPL而言,这种验证仅仅确保代码会执行,对于DSL而言,由于它们的简洁和领域结盟,验证经常可以确保代码将生成正确的结果。
增进合作
跨组织使用相同的业务相关的语义,促进了信息的共享,降低了业务逻辑的实际实现与业务用户的预期之间不符的风险。
业务规则引擎支持用相应的规则语言表达的规则的评估。它们的主要功能是管理事实的集合,并评估由几个断言之一组成的规则组。处理大量的事实,并且有效地评估断言,这是规则评估的主要挑战之一。根据业务规则定义,用业务规则语言表达,业务规则引擎一般提供一些映射机制来生成更低级别的执行代码——一般是通用的语言类。那些类可以用作一个更大业务组件的部分实现。这种方法的一种直接的后果是,业务规则的实现生命周期与它们所属的业务组件的生命周期紧密地结合在一起。
业务规则实现的灵活性和可修改性,通过激活动态变化的规则维护支持而实现(使用初始的规则语言)。这种能力提供了一种动态地修改业务规则的方法,并且不用重新构建和重新部署实现来快速地适应改变了的业务环境。
声明式的编程(例如规定什么)代表规则的选择模型:根据规则取值为true还是false,有些东西得以触发(例如动作)。控制流(例如这些调用的顺序)是隐式的,并在规则触发时显现出来。
业务流程
“业务流程是通过将一个输入转换成一个更有价值的输出来创造价值的一组相互关联的活动。输入和输出都可以是工件和/或者信息,并且该转换可以由人类的操作员、机器或者两者来执行”5。包含一个业务流程的活动不包括任何过程级别的决策,不值得进一步的分解。业务流程定义可以被看作是实现一个特定目标的诀窍。类似于业务规则的情况,利用业务流程DSL和专门的业务流程引擎,业务流程的实现可以被明显地简化。
业务流程编程要求指定执行流程活动(控制流)和活动(数据流)之间数据交互的顺序和条件。典型的语言构造允许以扩展流程图或者限定状态机器的形式定义流程。
业务流程定义,以业务流程语言表达,一般直接由业务流程引擎执行。(引擎在内部可以编译或者解释业务流程语言。业务流程引擎支持流程活动执行的协调和它们之间数据传播。在资源约束之下,管理多个异步处实例的同步执行,是业务流程引擎的主要挑战之一。
因此,业务流程实现与活动的实现分离,由业务流程编制。这样提供了将变化引入到业务流程的能力,不影响或者最小限度地影响底层的活动,从而给整个系统提供一种更高级别的可修改性。
必要的编程(例如规定如何)表示业务流程实现的选择模型:因为业务流程定义规定了它们的顺序,因此某些东西在其他某些东西之后被调用。控制流是显式的。
为了保持竞争力,公司必需不断地变革,并改善它的业务流程。从应用程序中将业务流程分解出来,并给它们允许简化实现和修改企业业务流程的实现,使用一种业务流程语言和引擎。
决策考量
说到最好地支持业务需求,并实现最佳的架构品质,确定正确的技术就变得很重要了。一天下来,假如使用了适当的DSL和引擎,那么业务规则和业务流程模型之间的实现选择则取决于两大因素:
说到规则与业务流程引擎的能力对比,应该考虑到以下几点:
- 同步性。规则评估是同步的,并且规则引擎(rules engines)被设计成尽可能迅速地评估业务规则。另一方面,流程一般来说本质上就是长运行且异步的。流程引擎(process
engines)的长处在于支持长运行流程的能力,在这里,动作可以花很长的时间来完成。因此,它们提供流程异步调用所需要的机制,例如请求/响应的关联、补偿,等等。
- 状态性。规则引擎是无状态的,当规则触发引擎时,一般会从输入参数或者知识库中拖出它的输入,对它进行评估,然后更新知识库或者将结果传播到输出。业务流程引擎专门设计用来保存每一个活动的流程实例的状态,在活动调用之间对它进行转换(hydrate)和保存,并为下一个活动的执行将它再次转换(re-hydrate)。
- 决定性。规则引擎触发其条件同时评估的业务。然而,它们的顺序是不确定的。业务流程大部分是确定的3,人们一般增加制约与平衡(checks
and balances)来确保确定性。
- 粒度。虽然业务规则本身可以在公司级别使用,但是它们一般被当作组件。它们本身提供一种更小的粒度,并从维护和部署角度来提供一种更高级别的灵活性。另一方面,业务流程更可以被看作是固定资产,它更不可能经历超时的巨大改变。
如前所述[1],SOA设计是基于企业业务模型从上到下的分解,如顶级的业务流程集合所定义的。在这种方法(图1)中,顶级的业务流程定义了一组活动,它们组成高级的业务服务。这些服务经常依次被当作流程,这导致递归的分解。最后,服务被实现为一组组件的协调,它展现这个分解的叶元素。
图1分等级的分解
在这种情况下,业务组件的不同实现可以包括现有企业功能的“包装”4,新的实现使用通用的编程语言,业务规则基于一个组件,编制则基于多个组件。
基于以上这种分解方法,SOA实现中一般出现业务流程/规则的下列用法:
- 业务流程实现业务服务编制
- 业务规则实现业务组件,它们是服务实现的一部分
- 业务组件负责指定服务内部其他组件的编制
最终不受这个分解所影响的,是在业务流程执行中给决策的实现使用业务规则。
什么是适当的技术?
根据上述业务流程/业务规则引擎能力和SOA分解的对比,选择技术时可以参考下列建议:
服务编制
服务编制一般流程外部活动/服务的长运行和异步的调用。如今的业务规则引擎不支持这些功能。业务流程语言/引擎,专门设计成定义和执行利用异步调用的长运行协作,是服务编制最适当的模型。
业务组件实现
当提到业务组件的实现时,对于只用同步交互的短期事务实现来说,业务规则和业务流程之间的界线变得模糊起来。它们经常可以定义相同的问题,从而利用其中任何一项技术进行解决。
让我们来看一下索赔手续费计算的例子5。索赔可以依照统一比例的手续费,或者损失换算系数(loss
conversion factors,LCF)。在前一种情况下,统一比例的手续费可以分别应用于作为整体的索赔,或者索赔的每一个词尾。这些不同方法的组合产生了三种截然不同的索赔手续费计算规则。这些规则组可以被表示为一组规则(图2),或者表示为一个流程(图3)。
图2:利用这些规则计算索赔手续费的示意图
图3:利用流程计算索赔手续费的示意图
因此,根据设计—时间模型,人们可以考虑使用一个规则组或者一种业务流程方法来解决相同的问题。
- 在这种情况下使用业务流程方法的好处,被简化为支持外部活动(服务)的调用。
- 在这种情况下使用业务规则方法,是不用重新编译而改变规则,和重新部署业务规则组件,以及在组件级别重用被实现的业务逻辑的能力(与处理业务流程时的服务级别相反)。
实现控制业务流程执行的业务规则
在规则定义业务流程本身的执行的情况下,必需考虑它们的复杂性和变化的频繁度。
现代的业务流程引擎一般提供评估简单规则的功能,构建在业务流程语言中,或者通过调用通用的语言。从而,在业务流程引擎中实现“简单的”业务规则是完全可行的。然而,在这种情况下,规则中的任何变化都将需要完全的测试和业务流程的部署。至于复杂的业务规则,它们一般需要利用规则引擎从过程中被提取,并被实现为一项独立的服务。
另一种典型的场景,是当业务流程本身(过程结构)相当稳定,而管理活动事务的规则虽然相当简单,却可能相当经常地改变的时候(请见图4)。在这种情况下,将规则实现外部化为独立的服务,利用规则引擎实现,可以显明地改善整体解决方案的可维护性。在这种情况下,业务规则支持业务规则中动态变化的能力,允许修改业务流程实现,而不用对它进行改变和重新部署。
图4:服务、流程和规则的典型变化比例
整体的SOA实现
图5展现了业务流程和规则引擎在SOA实现中的典型用法
图5:业务流程和规则引擎在SOA中的典型用法
从上图中我们可以看到,SOA实现中一种普遍的模式是:用规则引擎作为服务实现的一部分,并利用业务流程引擎进行服务编制。当规则控制其协调足够复杂的活动,或者变化比流程本身更快时,因此它们需要使用规则引擎,这些规则一般被具体化为一项特殊的规则服务,通过业务流程引擎调用。由于这个服务调用可能比(网络电话)一些业务流程引擎更贵,例如Microsoft的Biztalk
2004、IBM的WebSphere Process Server、PegaSystems的Smart
BPM Suite,以及把业务流程和规则引擎结合在单个应用程序中的其他产品。
结论
业务流程和业务规则不应该被当作是在相互竞争,而应该作为相互补充的技术。业务流程定义一组为了执行业务功能而需要被执行的活动。业务规则提供一种加值法来实现那些活动,通过提供一种较高级别的灵活性和可配置性,来适应快速变化的业务环境。 |