使用 Drools 構建業務規則引擎 - 中小企業的力量
已發表: 2022-03-11從事軟件開發工作最令人驚奇的事情之一就是能夠在許多不同的行業工作——尤其是如果你是一名顧問。 您在一個行業工作時學到的大多數軟件開發技能都可以直接轉移到任何數量的其他行業、公司、項目和利基市場。
我說的是數據庫設計、設計模式、GUI 佈局、事件管理等主題。當然,還有針對特定行業、公司或項目的主題。
中小企業遇上 IT,知識轉移開始
這就是主題專家 (SME) 的用武之地。SME 通常會非常參與項目的設計階段。
SME在行業內工作了很長時間,懂行話,懂編碼背後的業務邏輯。 中小企業可能對軟件開發有一定的了解,但這並不是項目成功的必要條件。
對於很多項目來說,除非軟件開發者對業務邏輯有深入的了解,否則完成一個成功的軟件應用程序會比較困難。 需要花費在知識轉移上的時間量將根據項目的複雜性而有很大差異。
假設採用敏捷方法並且在整個項目開發階段有一個或多個 SME 可用,則知識轉移將在項目的所有階段繼續進行。
如果完全的知識轉移不可行怎麼辦?
取決於行業和項目,中小企業可能無法提供完整的知識轉移。
例如,假設 SME 是一位擁有 25 年經驗的醫生,而您有 6 個月的時間來完成一個項目。 或者,將 SME 想像成擁有 40 年經驗的生物學家——這樣的知識水平根本無法在軟件開發項目的現實時間框架內轉移。
但是如果知識領域是動態的呢?
通常,軟件會根據時間或功能按設定的時間表發布。 但是,某些行業的業務規則變化得更頻繁。
在許多情況下,為了跟上行業變化而頻繁發佈軟件可能是不可行的。 在這種情況下,能夠在業務規則引擎中外部化業務規則可能是有意義的。 軟件項目能夠承受變化的能力將大大有助於確保其最終的長期成功。
規則引擎何時何地有意義?
對於許多軟件項目,完全的知識轉移是可行的,並且業務邏輯可以用計算機語言(如 C# 或 Java)進行編碼。
但是,有一部分項目對特定主題的理解量如此之大,或者業務規則受到如此多的更改,以至於非程序員直接訪問業務邏輯更有意義。 這是本教程的主題; 考慮到這一點,讓我們深入討論規則引擎。
什麼是業務規則引擎?
規則引擎是用於執行業務規則的工具。 業務規則由事實和條件語句組成。 任何出現在傳統業務邏輯中的“if-then”語句都符合業務規則。
例如:如果員工連續生病超過 5 天且沒有醫生證明,則需要將其記錄下來。 如果超過 6 個月沒有聯繫業務夥伴並且他們在此期間沒有進行任何購買,那麼可能是時候向他們發送一封誠摯的電子郵件了。 如果患者體溫高、視力有問題,並且有青光眼家族史,那麼可能是時候要求進行額外的 MRI 或其他檢查了。
中小企業如何編寫業務規則?
IT 不會期望 SME 學習 Java、C# 或其他編程語言,而是會為他或她創建一種迷你語言來表達他們的業務規則。 這些規則的構建塊將包含可以查詢的事實。 按行業/實踐領域劃分的一些事實示例如下:
- 人力資源:薪水、職位、經理、在公司工作的年限
- 醫療:體溫、血壓、當前用藥
- 財務:當前股價、52 週最高/最低價、市盈率、下一次財報發布日期
從本質上講,必須以簡化的方式為 SME 提供做出業務決策所需的信息。
這些規則是什麼樣的?
在本規則引擎教程的其餘部分,我將使用 Drools,這是一個基於 Java 的開源規則引擎,可以在 www.drools.org 找到,它是一個 JBoss 項目。 在 Drools 中,規則被編寫為 Java 代碼並具有以下結構:
導入語句在這裡:
rule “Name of rule” when “The if” part of the business logic goes here. then The “then” part of the business logic goes here. end
流口水和工作記憶
Drools 採用了一個稱為工作記憶的概念。
應用程序代碼將負責將適當的事實加載到工作內存中,以便 SME 可以編寫查詢這些事實的規則。 只有與應用程序業務邏輯相關的事實才應加載到工作內存中,以保持規則引擎以最高速度運行。
例如,如果應用程序正在確定是否批准客戶的貸款,則相關事實將包括工資、信用評分和未償貸款。 不相關的事實將包括星期幾或性別。
規則評估
在 Drools 工作記憶加載了規則和事實後,規則會根據規則的“then”部分進行評估。 如果“then”部分的計算結果為 true,則將執行規則的“when”部分。
通常,所有規則都會被一次評估,儘管可以將規則組合在一起並在每個組的基礎上進行評估。 規則的“then”部分可以改變工作記憶的內容。 發生這種情況時,Drools 將重新評估所有規則以查看是否有任何規則現在評估為真。 如果是這樣,它們的“何時”部分將被執行。
規則評估的這種遞歸性質可能是福也可能是禍——因此在創建規則時需要牢記這種架構。
Drools 規則的“如果”方面
在 Drools 中,事實由對象表示。 可以查詢對像類型的存在或不存在。 此外,還可以查詢對象的屬性。
這裡有一些例子:
確定員工的收入是否超過 100,000。
Employee(salary > 100000)
確定患者的膽固醇水平是否高於 200 並正在服用立普妥。
Patient(cholesterol > 200, medications.contains(“lipitor”))
確定股票價格是否在其年度最高價的 1% 以內。
Stock(price >= (yearHigh * .99))
組合查詢
在編寫複雜的業務邏輯時,業務規則可以通過使用布爾運算符 AND、OR 和 NOT 以及使用括號進行嵌套來組合查詢。
例如:
確定是否有一名經理的收入低於 75,000 美元或一名董事的收入低於 100,000 美元。
Employee(position.Equals(“Manager”),salary<75000) OR Employee(position.Equals(“Directory”),salary<100000)
使用多種對像類型
到目前為止,所有示例都基於單一對像類型,例如 Employee 或 Patient。 然而,Drools 允許查詢基於多種對像類型。
例如:
確定客戶的薪水是否高於 50,000 美元並且尚未申請破產。
Customer(salary>50000) AND not exists Bankruptcy()
規則的“當時”一面
規則的“then”部分決定了當規則的“when”部分至少有一個結果時會發生什麼。
在 Drools 中,任何可以用 Java 編寫的東西都可以寫在規則的“then”部分。 但是,為了使規則更可重用,最好不要在規則中放置任何 I/O、流控制代碼或一般執行代碼。
作為替代方案,規則的“then”部分可用於修改工作記憶。 一種常見的做法是在規則被評估為真時將事實插入到工作記憶中。
例如:
rule “LoanApproved” when Customer(credit>700) && not exist LoanOutstanding() then insert(new LoanApproval()) end
我們如何知道規則何時被評估為真?
觸發所有規則後,應用程序需要知道哪些規則被評估為真。 如果規則在評估為真時將對象插入到工作內存中,則可以編寫代碼來查詢這些對象的工作內存。

在上面的例子中,在所有規則都被觸發之後,可以進行查詢以查看 LoanApproval() 對像是否在工作內存中。
query "GetLoanApproval " $result: LoanApproval() end
業務規則引擎如何與應用程序交互?
典型應用程序包含業務邏輯、GUI、I/O 和控制代碼流。
例如,應用程序可能會像這樣處理用戶請求:
GUI ? Flow Control ? I/O ? Business Logic ? I/O ? Flow Control ? GUI
嵌入規則引擎會為此過程添加幾個步驟:
GUI ? Flow Control ? I/O ? Create Rules Engine Session ? Add Facts to Working Memory ? Fire Rules ? Determine which rules have evaluated true ? I/O ? Flow Control ? GUI
中小企業如何使用規則?
創建、編輯和刪除規則
為了讓 SME 使用規則,他們需要一個用戶友好的 GUI。 一些業務規則引擎附帶這樣的接口。
例如,Drools 附帶了兩個我認為用戶友好的 GUI。 第一個類似於電子表格,允許中小企業創建規則而無需編寫任何實際代碼。 第二個 GUI 允許創建更複雜的業務邏輯。
雖然這兩個 GUI 都有助於輸入簡單的條件,但隨著業務邏輯變得更加複雜,它們將不起作用。 在這種情況下,您必須創建自己的自定義 GUI。
SME 自定義 GUI 的元素
為了使 SME 有效工作,請考慮創建具有以下功能的自定義 GUI:
- 語法檢查器——“檢查語法”按鈕可以調用 Drools 代碼來檢查可能的錯誤及其行號。
- 拖放 - 與其要求 SME 記住他們可用的對象和屬性,不如考慮為他們提供一個選擇列表,他們可以從中拖放。
- Web 界面 – 中小企業可以使用瘦客戶端界面,無需擔心分配問題。 這將派上用場,因為 GUI 需要附加功能和一般維護。
- Rule Tester – 能夠在不與整個應用程序交互的情況下測試單個規則將大大提高 SME 的生產力。 允許 SME GUI 確定事實,然後觸發個別規則。
規則應該存儲在哪裡?
在 Drools 中,通常有兩種存儲規則的方法。 Drools 開箱即用,基於文件的規則通常具有 .drl 擴展名。
當規則的數量很少時,這很有效。 隨著規則數量的增加,您將需要使用數據庫。 從數據庫存儲和檢索規則需要更多的工作,但應該為您提供更易於管理的架構。
本規則引擎教程僅涉及 Drools 規則語言的一小部分。 有關完整說明,請參閱官方參考文檔。
不應輕易做出使用規則引擎的決定。 雖然規則引擎將使您的應用程序更容易被 SME 擴展,但它的開發、測試和部署也會變得更加複雜。 有關此主題的其他注意事項,您可能需要查看以下指南。
現在我們可以繼續向您展示一些更有趣的東西——一個簡單的 Drools 實際示例,在大多數 Toptal 博客讀者應該熟悉的用例中。
在真實場景中使用 Drools
Toptal 是高級軟件開發人才的領先供應商,目前使用申請人跟踪軟件在招聘過程的各個階段引導求職者。 這是此過程的簡化可視化流程圖:
目前,決定應聘者是否繼續招聘流程的業務邏輯已被硬編碼到軟件中。 每次人力資源部需要更改業務邏輯時,都必須讓 IT 參與其中。 他們希望能夠直接改變他們的軟件運行方式。
申請人跟踪軟件將被修改為在招聘過程中的每個決策點運行 HR 提供的規則。 HR 將有一個“候選人”對象,該對象將代表一個求職者,該求職者的狀態剛剛因初次進入、完成在線考試或許多不同的因素而被修改。 Candidate 對象將具有表示經驗、考試成績、面試成績等的字段。
以下示例提供了一組簡化的規則供您考慮。 它還沒有被部署,它只是一個簡單的例子,由四個相互關聯的規則組成:
- 已提交 -> 測試
- 測試 -> 面試
- 面試 -> 項目
- 項目 -> 招聘
已提交 -> 測試
根據當前客戶的需求,HR 想編寫一個規則來確定是否應安排候選人進行在線測試。
Rule “Schedule For Testing” when $candidate: Candidate(status=='Submitted',yrsExperience >= 10, skill(name=='Java', yrsExperience>=5) or Skill(name=='C#', yrsExperience>=5)) then $candidate.setStatus('Testing'); end
測試 -> 面試
候選人參加在線考試後,需要評估他們的分數。 HR 也想控制這條規則。 在線考試測試考生理解軟件開發理論、解決問題和語法的能力。 HR 想決定什麼樣的分數組合可以讓候選人被考慮參加技術面試。
Rule “Schedule For Interview” when $candidate: Candidate(status=='Testing', testScore(theory>.8 && syntax>.6 && problemSolving>.8); then $candidate.setStatus('Interview'); end
面試 -> 項目
技術面試將測試候選人談論他們的經驗、回答問題解決問題的能力,並將測試他們的一般溝通能力。 HR 將編寫確定技術面試及格分數的規則。
Rule “Schedule For Project” when $candidate: Candidate(status=='Interview', interviewScore(speakExperience>.9 && problemSolving>.8 && communication>.9 ); then $candidate.setStatus('Project'); end
項目 -> 招聘
如果候選人通過了技術面試,他們將獲得一個離線編程項目。 他們將提交項目,並將根據完整性、架構和 GUI 進行評判。
Rule “Schedule For Hiring” when $candidate: Candidate(status=='Project', projectScore(completeness>.8 && architecture>.9 && gui>.7 ); then $candidate.setStatus('Hiring'); end
如您所見,即使是這個基本示例也為 HR 提供了許多可能性,並且可以簡化操作。 HR 無需 IT 參與即可更改規則這一事實將不可避免地節省時間並加快篩選過程。
由於可以隨時更改規則,因此人力資源部門也將擁有更大的靈活性。 例如,HR 可以通過設置不同的參數來擴展或限制選擇過程。
如果有太多候選人勾選了所有正確的框,則可以在幾分鐘內提高標準,從而減少候選人的數量。 或者,如果該過程產生的候選人很少或沒有滿足所有要求,HR 可以選擇降低或放棄一些標準,將重點轉移到更相關的技能上,直到有足夠數量的候選人滿足要求。