2011-06-03 76 views
3

這個問題是由組織活動的公司使用的一個軟件。當活動發生變化時(狀態,開始時間,人數),需要通知某些人(通過電子郵件)。對此負責的代碼開始非常簡單:電子郵件正文包含所有舊值和已更改信息的新值。如何重構多個複雜的if-else分支

多年來,引入了許多小規則。例如:如果新狀態爲「已取消」,則郵件的主題應爲:「活動取消」而不是「活動已更改」。如果沒有以前的狀態(所以活動是新的),並且當前狀態是「最終」,則主題應該是「在[日期]上的新活動」,並且主體應該包含完整的概述(因此沒有改變)。

上面的這些規則只是爲了說明問題。還有更多(關於狀態/日期/時間等的組合),總計最多約500行代碼。

發生的問題是,此代碼目前很難理解和維護。新的規則時不時地被引入,並且添加它們而不破壞其他規則可能是一種痛苦。將這樣的代碼重寫成更容易理解和可維護的代碼的最好方法是什麼?目前,if-else分支的順序也非常重要。第一個if語句是最重要的,next else-if語句不那麼重要,直到最一般情況的最後else子句。

回答

4

聽起來像rules engine可以幫助。 Drools是一種選擇,但它幾乎肯定是完全矯枉過正!

你有接口代表規則嗎?類似於

public class Activity {} 

public interface Rule { 
    boolean applies(Activity); 

    Activity applyRule(Activity x); 
} 

鑑於此,您可以實現reduce函數以按順序應用規則,直到到達列表的末尾。

Activity applyRules(List<Rule> rules, Activity); 
+0

肯定聽起來像是一個不錯的選擇,將來看看這個。Drools對於這個應用程序似乎有點太多了,但是爲這個特定的情況編寫一個簡單的規則引擎不應該是太多的工作。你會如何推薦規則的排序? – Intru 2011-06-04 08:37:16

+0

我想這也必須進入規則引擎。規則排序有什麼樣的邏輯?匹配規則是否會影響下一個規則?也許它可以減少到決策樹? – 2011-06-04 11:46:29

2

我將會分離規則和他們的應用程序,讓你的代碼變得

For all Rules 
    if ThisRule.Applies(activity) then 
     ThisRule.ApplyActions(email); 
     break; 

的規則,那麼將是一個類,其中每個規則有適用和ApplyActions或ConstructEmail什麼的。

您按優先級順序構造規則列表。一旦完成,你只需要遍歷列表。

這樣做的要點是,規則不需要知道或關心其他規則,所有的規則都是有效的獨立的,他們只需要知道他們是否是給予他們的活動的規則,如果他們遵循該規則的行爲。

然後難題是分裂出不同的規則,例如,如果你有一個新規則被取消的規則,所以你必須放在頭部取消,但你有另一個規則也適用,那麼你需要一個機制來申請多個規則,例如:

For all Rules 
    if ThisRule.Applies(activity) then 
     ThisRule.ApplyActions(email); 
     if ThisRule.TerminalRule then 
      break; 

因此,像改變主題這樣的簡單規則也允許應用其他規則。