規則引擎二:Drools規則引擎
-
原文連結:http://www.it165.net/pro/html/201503/36286.html
-
Drools是一個開源的規則引擎,經過多年的發展,也提供如下商業BRMS具備的功能元件:
基於Eclipse的整合開發環境, 獨立集中的規則儲存庫 基於WEB的規則維護環境 提供decision table 和 ruleflow等規則製品為規則的執行書寫提供更多的靈活性本文將使用Drools來實現典型的風險評分,並將相關功能與IBM ODM/JRules做一個簡單比較。客戶風險評分具體需求參見"基於業務規則的客戶風險評分"一文。
模型
Drools一般使用JavaBean作為事實模型,因此我們可以重用之前建立的Java XOM工程。
Drools和IBM ODM/JRules在modeling方面的重要區別是,Drools沒有BOM/XOM這樣的兩層物件模型對映體系,Java型別可同時直接供規則使用,即領域模型和規則(事實)模型兩者是重疊的。雖然Drools也提供declarative的方式來定義規則模型,不過這種方式在我看來更多是作為Java型別的補充,而非用於解耦領域模型和規則模型(事實上兩者的耦合在某種程度上反而被加強了)。
Drools的這種設計當然從開發層面給使用者提供了相當的便利性和靈活性,但缺少專用的規則模型無疑會給業務規則設計治理帶來一定的麻煩,對於大型的複雜規則專案,這種麻煩可能是至關重要的。
規則流設計
IBM ODM/JRules中的規則流可以視為一個micro flow,僅僅用於規則執行的串聯,既不能long-running,也不支援人工任務,和通常所說的工作流是兩個不同的概念。Drools flow,其定位實際上是workflow,而非ruleflow(儘管其定義檔案的字尾為"rf"),這一點從它提供的元件可以看出,如Event Wait,Task, Human Task都是典型的工作流引擎任務。
至於Drools flow設計定位背後的緣由,Drools flow的文件解釋如下:
It is very difficult (and probably very inefficient as well) to extend a process engine to also take rules into account. The process engine would need to check for rules that might need to be executed at every step and would have to keep the data that is used by the rules engine up to date. However, it is not that difficult to "teach" a rules engine about processes. If the current state of the processes is also inserted as part of the Working Memory data the rules engine reasons about, and we instruct the rules engine how to derive the next steps of an executing process, the rules engine will then be able to derive the next steps taking rules and processes into account jointly.
這種控制反轉的思路在給流程提供了大量的靈活性的同時,使規則和流程可以無縫整合。一般的流程引擎,其流程的定義和規則決策通常是割裂的,流程決定何時即怎樣呼叫規則引擎,實現通常牽涉複雜的資料和程式碼整合。
在本文中,我們主要使用Drools flow實現規則執行控制,並不牽涉業務流程。
下面我們看看風險評分規則流在Drools中的具體實現:
規則流的設計基本上和ODM類似。由於Drools flow中不提供規則任務控制的某些特性,如initial action/final action,所以上圖多了PreScoring和PostScoring節點,分別用於定義scoring規則執行前後的動作。
規則設計
下面的程式碼段是eligibility規則的設計,這裡直接使用了drl規則語言(類似與IBM ODM中的irl語言)。
package com.decisionrule.riskrule import com.decisionrule.risk.*; global Result result; rule "check amount" ruleflow-group "eligibility" when req : Application(loanAmount > 1000000) then result.setQualified(false); result.addMessage("the loan amount is more than 1 million"); end rule "check age too young" ruleflow-group "eligibility" when req : Application(m : applicant) eval(m.getAge() < 18) then result.setQualified(false); result.addMessage( "the applicant is too young" ); end rule "check age too old" ruleflow-group "eligibility" when req : Application(m : applicant) eval(m.getAge() > 60) then result.setQualified(false); result.addMessage( "the applicant is too old" ); end |
Drools也提供DSL能力可以定義類自然語言的規則,不過個人感覺這種基於template和mapping實現的DSL缺乏一個真正語言的靈活性和擴充套件能力,在實際應用中不具備實用價值。我會在以後的blog中深入解釋一下規則DSL相關的話題,在此不展開討論。
風險要素的定義,風險評分和分級都是用了決策表,如下圖所示:
Drools決策表利用了excel spreadsheet作為規則編輯器,來定義多個引數化的規則,條件和動作都通過script定義在對應的單元格中,結合引數組裝成drl規則。這種實現思路總體而言是一種可行的輕量級的方式,從使用角度,需要結合兩個工具(excel和eclipse),定義的時候不太方便,不過一旦決策表定義完成,理論上是可以交付給業務人員維護的。一些使用注意事項:
RULEFLOW-GROUP屬性必須作為一個單獨列在每一行定義,無法根據整個決策表一次性定義 CONDITION列無法訪問global變數,必須實現把global變數放入工作記憶體 ACTION列中函式有多個引數時,無法把引數分開到多個列,必須在同一列中定義,用逗號分隔 決策表錯誤報告基於編譯後的drl,可以使用SpreadsheetCompiler將drl打印出來,方便排錯總結
總體而言,無論從功能角度還是易用性的角度,雖然和商業產品還有一定的距離,Drools都是可以滿足實際應用需求的。對於希望以較低的成本引入規則技術將業務邏輯從應用中剝離的企業,Drools是一個不錯的選擇。