分享

Drools 5.1.1

 且看且珍惜 2014-04-12

第 8章 规则和流程

Drools流是一个工作流和流程的引擎,它允许高度集成流程和规则。本章讨论规则和流程的集成,从简单方案到高级方案。

8.1  为什么在流程中使用规则

纯 粹依赖流程结构(如节点和线路)描述应用程序业务逻辑的工作流(Workflow)语言往往是相当复杂。尽管这些工作流结构很适合于描述一个应用程序的整 个控制流,但是描述复杂逻辑和特殊情况却相当困难。因此,可执行的流程往往变得非常复杂。我们相信,通过扩展流程引擎,支持声明式规则与这些标准流程结构 的结合,这种复杂性可以得到控制。

  1. 简单:复杂决策通常使用一组规则是更容易详细说明。使用规则的高级约束语言,能够更容易准确描述复杂的业务逻辑。描述业务逻辑的每一部分,都可以结合多条规则。
  2. 灵活: 规则和流程能够有一个独立的生命周期。这意味着我们可以改变描述某些关键决策点的规则,而不用改变流程本身。对不断变化的需求和环境,可能添加、删除和修改规则,微调流程的行为。 
  3. 不同的作用域:规则可以跨流程或者外部流程被重用。因此,你的业务逻辑没有被锁定在你的流程内部。
  4. 声明:关注描述“是什么”而不是“为什么”。
  5. 粒度:容易编写处理具体情况的简单规则。流程是更适合描述整个控制流,但是如果需要处理许多特殊情况,往往变得非常复杂。
  6. 数据为中心:规则能够轻松处理大型数据集。
  7. 性能:规则的计算被优化。
  8. 高级的条件和动作的语言:规则语言支持高级功能,如自定义函数、集合、条件元素、包括量词(including quantifiers)等等。
  9. 高级别:通过使用DSLs、业务编辑器、决策表和决策树,你的业务逻辑能够以一种业务用户可以理解(甚至可能编辑)的方式被描述。

8.2.  为什么在单个引擎中集成规则和流程?

  1. Drools流在一个软件产品中合并了流程和规则。与现有的流程和规则产品相比较,它有几个优点 。
  2. 简单:方便终端用户合并规则和流程。.
  3. 封装:有时候在流程和规则之间的紧密集成是有益的。
  4. 性能:没有不必要的传递、转换或数据的同步。
  5. 学习曲线:易于学习一个产品。
  6. 可管理性:易于管理一个产品,在一个更大型的知识信息库中,规则和流程可以是类似的东西。
  7. 功能集成:我们提供了一个集成的IDE、审计记录、基于网页的管理、信息库、调试等等。

8.3.  方法

工 作流语言描述了使用一个流程图时应该被执行的活动的顺序。流程引擎负责根据执行流程的当前状态选择应该执行的活动。另一方面,规则是由描述什么时候可以应 用一条规则的一组条件和在条件满足时被执行的一个动作构成。然后规则引擎负责计算和执行规则。它根据应用程序的当前状态决定需要被执行的规则。

工作流流程擅长于描述应用程序的整个控制流(可能是长期运行的)。然而,流程被用于定义复杂的业务决策,要处理许多特殊情况,和需要响应各种外面事件,实事上往往变得非常复杂。规则擅长于描述复杂的决策和大量数据或事件的推理。但是不常使用规则来定义长期运行流程。

在过去,用户被迫在使用流程或规则引擎定义他们的业务逻辑两者间做选择。关于大量数据需要推理的问题使用规则引擎,而用户想关注描述他们流程的控制流则被迫使用流程引擎。然而,如今的业务可能希望合并流程和规则,以便于他们能够以最适合的格式定义他们所有的业务逻辑。

基 本上,规则和流程引擎通过查看它的知识库(一组规则或流程,各自的)和应用程序的当前已经状态(在工作内存中的数据或执行流程的状态,各自的)得到需要被 执行的下一个步骤。如果我们希望集成规则和流程,我们需要一个引擎,它可以就在流程和规则两个内部定义的逻辑决定下一个步骤。

8.3.1.  教给规则引擎有关流程

扩 展流程引擎,还把规则考虑在内是非常困难(也可能是非常低效的)。流程引擎需要检查在每一步都需要执行的规则,并且必须保持规则引擎使用的最新数据。然 而,“教给”规则引擎有关流程是不困难的。如果当前的流程状态也被作为工作内存有关规则引擎推理数据的一部分插入,并且我们指示规则引擎如何得到一个执行 流程的下一个步骤,那么规则引擎将能够得到把规则和流程联合考虑的下一个步骤。

8.3.2.  控制反转

从流程的观点看,这意味存在有一个控制反转。常规的流程引擎行使完全控制,根据流程实例的当前状态得到下一个步骤。如果需要,它能够联系外部服务,检索附加信息,但是它独自决定要采取的步骤,并单独负责执行这些步骤。

然 而,只有我们扩展规则引擎(它能够联合规则和引擎推理)才能得到把规则和流程两个联合考虑的下一个步骤。如果需要执行流程的一部分,规则引擎会请求流程引 擎执行这个步骤。 一旦这个步骤已经执行,流程引擎返回控制给规则引擎,再得到下一个步骤。这意味着下一步该做什么已经被反转:流程引擎自身不再决定要获得的下一个步骤,但 是我们增加的规则引擎会控制、通知流程引擎在什么时候执行什么东西。

8.4.  例子

 drools-examples项目包含了一个样本流程(org.drools.examples.process.order),用于说明合并流程和规则的一些优势。 这个流程描述了一个订单应用程序,校验进入的订单、计算折扣和申请货物航运。

8.4.1.   计算在你的流程中的一组规则

Drools流可以轻松地包括一组规则作为流程的一部分。需要被计算的规则,应该使用ruleflow-group规则属性,分组在一个规则流组中。
当 激活一个RuleSet 节点时,该分组触发在你的进程中这些规则的计算。这个例子在流程中使用了两个 RuleSet节点 :一个用于验证订单,一个用于计算折扣。例如,用于验证订单的规则之一,显示如下。注意,ruleflow-group属性,它确保这个规则作为具有下图 中显示了相同规则流组的RuleSet 节点的一部分被计算。

rule "Invalid item id" 

   ruleflow-group "validate" 

   lock-on-active true 

when

      o: Order()

      i: Order.OrderItem() from o.getOrderItems()

      not (Item() from itemCatalog.getItem(i.getItemId())) 

then 

      System.err.println("Invalid item id found!"); 

     o.addError("Invalid item id " + i.getItemId()); 

end

 

Drools 5.1.1_DOC (52) - *工* - 要有光,于是就有了光

 图8.1. RuleSet节点和它的规则之一

8.4.2.  使用规则计算约束

可 以在你的流程中使用规则表达和计算复杂约束。例如,在一个Split节点决定执行路径的选择时,可以使用规则来定义这些条件。相似的,一个 Wait 状态可用一条规则来定义等待期限。这个例子使用规则决定在验证订单后的下一个动作。如果订单包含错误,一个销售代表应该尝试修正订单。订单的价格> 1000$ 是更重要的,那么一个高级代表应该照料该订单。所有其他订单只应该正常处理。 一个决定节点被用于选取这些选择之一,并且规则被用来描述它们每一个的约 束。


Drools 5.1.1_DOC (52) - *工* - 要有光,于是就有了光
8.4.3.  分配( Assignment )规则

可以在一个流程中使用人类(Human)任务,描述需要由人类参与者执行的工作。 可以根据流程的当前状态和历史选择参与者。分配规则描述了如何根据这些信息决定参与者。每当一个新的人类任务需要被执行,那么这些分配规则会被自动应用。

注意,显示在下面的规则是用域特殊语言( Domain Specific Language -DSL)编写,针对在订单处理环境中的具体要求制定条件。

/********** Generic assignment rules **********/ 
   rule "Assign 'Correct Order' to any sales representative"
      salience 30
      when
          There is a human task
          - with task name "Correct Order"
          - without actor id
      then
           Set actor id "Sales Representative"
  end
 /********** Assignment rules for the RuleSetExample process **********/
    rule "Assign 'Follow-up Order' to a senior sales representative"
      salience 40
      when
          Process "org.drools.examples.process.ruleset.RuleSetExample" contains a human task
          - with task name "Follow-up Order" 
         - without actor id
      then
           Set actor id "Senior Sales Representative"
  end

8.4.4.   使用规则描述特殊情况

规则可以被用来描述特殊情况,以及如何响应这些特殊情况。在正规流程的控制流中添加所有这些信息使基本流程变得更复杂。规则可以被用来分别处理各个这些情况,使核心流程保持简单的格式。它也使它更容易适合现有的流程考虑先前未曾预料的事件。

8.4.5.  使用规则模块化关注点

流 程定义了整个控制流。规则可以被用来为这个流程添加附加关注点,不必使整个控制流更复杂。例如,规则可以被用来记录在流程执行期间的某些信息。不改变原始 流程,而所有日志功能作为一组规则被清楚地模块化。这极大地改善可重用性(允许用户轻松地对不同的流程应用相同的策略)、可读性(不改变原始流程的控制 流)和可维护性(由于日志策略规则从那些流程本身的分离)。

8.4.6.  规则用于动态改变流程行为

规 则让你动态地细调你的规则的行为。假设在运行期间有一个流程遭遇了一个问题。现在,在运行期间,可以添加新规则,记录附加信息或者处理特定流程的状态。一 旦问题被解决或者环境已经改变,这些规则可以轻松地再次被删除。根据当前状态,可以动态地选择不同的策略。例如,根据当前加载的所有服务,规则可以被用于 为当前加载优化流程。这个流程包含了一个简单例子,允许你为 "Check Order"任务动态地增加或删除日志。当在主应用程序窗口中的"Debugging output"复选框被选取,只要"Check Order"任务被请求,规则显示下面的动态加载,写记录输出到控制台。取消该框的选取,将动态地再次删除规则

rule "Log the execution of 'Correct Order'"

      salience 25

when

      workItemNodeInstance: WorkItemNodeInstance( workItemId <= 0, node.name == "Correct Order" )

      workItem: WorkItemImpl( state == WorkItemImpl.PENDING ) from workItemNodeInstance.getWorkItem() 

then

      ProcessInstance proc = workItemNodeInstance.getProcessInstance(); 

     VariableScopeInstance variableScopeInstance =   (VariableScopeInstance)proc.getContextInstance( VariableScope.VARIABLE_SCOPE ); 

     System.out.println( "LOGGING: Requesting the correction of " +   variableScopeInstance.getVariable("order")); 

end

8.4.7.  集成工具

在Drools Eclipse IDE中集成了流程和规则。 流程和规则被简单地看作业务逻辑的不同类型,管理几乎是相同的。例如,加载一个流程或一组规则到引擎是非常相似的。另外,不同规则的实现,如DRL或 DSL,都以统一的方式被处理。

private static KnowledgeBase createKnowledgeBase() throws Exception {

      KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); 

      kbuilder.add( ResourceFactory.newClassPathResource( 

                   "RuleSetExample.rf", OrderExample.class), ResourceType.DRF ); 

     kbuilder.add( ResourceFactory.newClassPathResource(

                    "workflow_rules.drl", OrderExample.class), ResourceType.DRL ); 

     kbuilder.add( ResourceFactory.newClassPathResource(

                    "assignment.dsl", OrderExample.class), ResourceType.DSL );

      kbuilder.add( ResourceFactory.newClassPathResource(

                   "assignment.dslr", OrderExample.class), ResourceType.DSLR );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

      kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );

      return kbase;  }

 

我们的审计日志也包含一个集成视图,显示规则和流程序是如何相互影响。例如,日志的一部分,显示了规则"5% discount" 如何被作为节点"Calculate Discount"的部分被执行。


Drools 5.1.1_DOC (52) - *工* - 要有光,于是就有了光

8.4.8.  域特殊规则和流程

定义规则不需要使用核心规则语言的语法,而定义它们还可以使用我们更高级的规则编辑器,使用域特殊语言,决定表,向导编辑器等等。我们的例子定义了一个域特殊语言,用于根据任务的类型、它的属性、定义它的流程等等描述分配规则。这使分配规则让非专家人士更好理解。

/********** Generic assignment rules **********/ 

   rule "Assign 'Correct Order' to any sales representative"

      salience 30 

     when 

         There is a human task

          - with task name "Correct Order" 

          - without actor id

      then 

          Set actor id "Sales Representative"

  end

 

   /********** Assignment rules for the RuleSetExample process **********/

    rule "Assign 'Follow-up Order' to a senior sales representative"

      salience 40

     when

          Process "org.drools.examples.process.ruleset.RuleSetExample" contains a human task

          - with task name "Follow-up Order"

          - without actor id

      then

           Set actor id "Senior Sales Representative"

  end

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多