2015-07-20 26 views
0

的我的工作,其中從velocity template動態創建的每個.drl文件Drools項目。我已經編寫了在.drl文件本身的then成功條件檢查後執行的每個計算和操作。性能和使得Java的可維護性調用「然後」 Drools的

讓我們假設一個簡單的條件

rule "Rule %" 
no-loop 
salience 10 

when 
    $var: Map(this["Key"] == "SomeValue") 
then 
    $var.put("Discount%", Do-SOME-%-CALCULATION AND PUT IT HERE) 
end 

rule "Rule Amt" 
no-loop 
salience 9 

when 
    $var: Map(this["Key"] == "SomeValue") 
then 
    $var.put("DiscountAmt", Do-SOME-Amt-CALCULATION AND PUT IT HERE) 
end 

rule "Rule % Amt" 
no-loop 
salience 8 

when 
    $var: Map(this["Key"] == "SomeValue") 
then 
    $var.put("Discount%", Do-SOME-%-CALCULATION AND PUT IT HERE) 
    $var.put("DiscountAmt", Do-SOME-Amt-CALCULATION AND PUT IT HERE) 
end 

形成這些類型的DRL文件,我已經形成了velocity template like this

#set($d = "$") 

rule "$rule.name $rule.type" 
no-loop 
salience $rule.priority 

when 
    ${d}var: Map(this["$rule.keyName"] == "$rule.keyValue") 
then 
    #if($rule.type == "%") 
     ${d}var.put("Discount%", CODE-FOR-%-CALCULATION); 
    #elseif($rule.type == "Amt") 
     ${d}var.put("DiscountAmt", CODE-FOR-AMT-CALCULATION); 
    #elseif($rule.type == "% Amt") 
     ${d}var.put("Discount%", CODE-FOR-%-CALCULATION); 
     ${d}var.put("DiscountAmt", CODE-FOR-AMT-CALCULATION); 
    #end 

我知道,最後#elseif($rule.type == "% Amt")可以利用前兩個被淘汰ifelseif通過將|| $rule.type == "% Amt"置於這兩種情況下。但這只是一個例子。

只是假設我沒有任何選擇來簡化這些3條件到2條件,但重複我的代碼本身。相信我,我有更多的計算,我必須在速度代碼中重複這些代碼多種類型。這整體變得混亂。因爲,如果我必須對公式做一些小改動,我必須對速度模板中的所有重複代碼進行更改,如果我們錯過了重複代碼中的更改,肯定會導致人爲錯誤。

這就是爲什麼我認爲寫了Java類的公式和計算,只需撥打電話到類.drl。所以.drl.vm

.drl

import com.package.util.RuleUtil; 

rule "Rule %" 
no-loop 
salience 10 

when 
    $ruleUtil: RuleUtil() 
    $var: Map(this["Key"] == "SomeValue") 
then 
    $ruleUtil.discountPer($var); 
end 

rule "Rule Amt" 
no-loop 
salience 9 

when 
    $ruleUtil: RuleUtil() 
    $var: Map(this["Key"] == "SomeValue") 
then 
    $ruleUtil.discountAmt($var); 
end 

rule "Rule % Amt" 
no-loop 
salience 8 

when 
    $ruleUtil: RuleUtil() 
    $var: Map(this["Key"] == "SomeValue") 
then 
    $ruleUtil.discountPer($var); 
    $ruleUtil.discountAmt($var); 
end 

.vm

#set($d = "$") 

rule "$rule.name $rule.type" 
no-loop 
salience $rule.priority 

when 
    ${d}ruleUtil: RuleUtil() 
    ${d}var: Map(this["$rule.keyName"] == "$rule.keyValue") 
then 
    #if($rule.type == "%") 
     ${d}ruleUtil.discountPer(${d}var); 
    #elseif($rule.type == "Amt") 
     ${d}ruleUtil.discountAmt(${d}var); 
    #elseif($rule.type == "% Amt") 
     ${d}ruleUtil.discountPer(${d}var); 
     ${d}ruleUtil.discountAmt(${d}var); 
    #end 

如果你想知道有多少次我重申,折扣公式代碼,我會說最低10次,並且涉及多種折扣計算的重複次數。 TBH,當看到.vm代碼時,我感到惱火。因爲所有這些代碼重複性和長期可維護性差。我想知道是否堅持使用當前的代碼(當前vm代碼涉及多個代碼重複並且難以維護)還是應該通過實現我提出的結構將所有這些公式計算移至Java方法。我不知道它會影響我的.drl文件性能。任何建議將不勝感激。

注:我更喜歡代碼的可維護性最。在接管這個項目後,我不想讓別人傷腦筋。當然,我也不想在做任何小小的改變時打破我的頭腦。

回答

1

你還沒有提出使用模板的情況。這可能是因爲你選擇了第二個最好的方法來開始。

這就是說,我的意見(基於使用模板很多,雖然沒有產生DRL)是使模板邏輯儘可能簡單。我不會將任何公式放入模板中 - 堅持使用(靜態)RuleUtil方法。

請注意,您不需要將RuleUtil作爲一個事實 - 只需導入該類即可引用其靜態方法。

即使是最後一個tmeplate中簡單的if-elsif語句也是我試圖避免的。鑑於這一規則類型可以是數量,百分比和PercentAmount之一,你可以寫

rule "$rule.name $rule.type" 
when 
    ${d}var: Map(this["$rule.keyName"] == "$rule.keyValue") 
then 
    ${d}ruleUtil.discount$rule.type(${d}var); 
#end 

我省略了顯着性和無環路:我沒有看到的原因,第二和第一幾乎總是像這些規則的壞主意。

最後:我不喜歡Map作爲一個事實 - 但也許有一個很好的理由不使用bean風格的事實類。

+0

感謝您的想法。我有一個小小的懷疑。我的流口水是動態形成的。所以我不知道有多少事實可以在'when'中出現..就像我可能有'$ var:Map(),$ var1:Map(),$ var2:Map()等等。任何方式我都可以獲得在'when'中聲明的事實列表,我的意思是我想要在'then'內部提供所有事實的列表。 –

+0

如果發電機能夠產生LHS列表,它肯定應該能夠在RHS上做同樣的事情。如果你在java.util.List中需要它們,你就可以擁有所有的Java。但似乎這是另一個問題。 – laune