我是Drools的新手,正在阅读这本书:Mastering JBoss Drools 6
第2章展示了一个例子,我们创建了一个Customer
和Order
,根据客户的订单大小对他们进行分类,给出折扣并生成Coupon
。
该示例提到:
- 一位顾客
- 客户有一个包含5个项目的订单,因此归类为
SILVER
客户 - 每件物品的价格超过500,因此归类为
HIGH_RANGE
物品 - 客户是
SILVER
客户,因此创建了Coupon
- 对于订单超过2个项目的每个
SILVER
客户,给予10%的折扣
下面是Drools的规则:
add-discount.drl
rule "High Range order - 10% discount"
when
$o: Order($lines: orderLines, orderLines.size >= 2, $customer: customer, discount == null)
$c: Customer(category == Customer.Category.SILVER, this == $customer)
forall(
OrderLine(this memberOf $lines, $item: item)
Item(this == $item, category == Item.Category.HIGH_RANGE)
)
then
modify($o){
setDiscount(new Discount(10.0))
}
end
classify-customer-rules.drl
rule "Classify Customer by order size"
when
$o: Order( orderLines.size >= 5, $customer: customer )
$c: Customer(this == $customer, category == Customer.Category.NA)
then
modify($c){
setCategory(Customer.Category.SILVER)
}
end
classify-items-rules.drl
rule "Classify Item - Low Range"
when
$i: Item(cost < 200, category == Category.NA)
then
$i.setCategory(Category.LOW_RANGE);
update($i);
end
rule "Classify Item - Mid Range"
when
$i: Item(cost > 200 && cost < 500, category == Category.NA)
then
$i.setCategory(Category.MID_RANGE);
update($i);
end
rule "Classify Item - High Range"
when
$i: Item(cost >= 500, category == Category.NA)
then
$i.setCategory(Category.HIGH_RANGE);
update($i);
end
coupons-creation.drl
rule "Create Coupons for silver customer"
when
$o: Order($customer: customer)
$c: Customer(this == $customer, category == Customer.Category.SILVER)
then
Coupon x = new Coupon($c, $o, Coupon.CouponType.POINTS);
System.out.println(x);
insert(x);
end
执行的规则数应为8。5个要分类的项目(5个规则)+1个要分类的客户(1个规则)+1个要添加的折扣(1个规则)+1个要创建的优惠券(1个规则)
但实际触发的规则数是9条,Here是我用来检查的测试,优惠券创建规则触发了两次,我不明白为什么,我检查了触发规则后创建的优惠券数,如下所示:
Collection<Coupon> coupons = Util.getFactsFromSession(kieSession, Coupon.class);
coupons.forEach(x -> System.out.println(x));
在优惠券创建规则中还有一个print语句。
这是我得到的:
12:54:47.607 [main] DEBUG org.drools.core.impl.KnowledgeBaseImpl - Starting Engine in PHREAK mode
12:54:47.730 [main] DEBUG org.drools.core.common.DefaultAgenda - State was INACTIVE is nw FIRING_ALL_RULES
12:54:47.732 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop
12:54:47.795 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop
Coupon created com.example.droolstut.model.Coupon@b14cb989
12:54:47.797 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop
12:54:47.797 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop
12:54:47.799 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop
12:54:47.806 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop
Coupon created com.example.droolstut.model.Coupon@424f842a
12:54:47.806 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop
12:54:47.806 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop
12:54:47.806 [main] DEBUG org.drools.core.common.DefaultAgenda - State was FIRING_ALL_RULES is nw HALTING
12:54:47.806 [main] DEBUG org.drools.core.common.DefaultAgenda - State was HALTING is nw INACTIVE
Coupon found: com.example.droolstut.model.Coupon@424f842a
Coupon found: com.example.droolstut.model.Coupon@424f842a
因此,看起来该规则执行了两次,但在执行后只找到了第二张优惠券。
但是,当我在调试模式下运行测试时,优惠券规则只执行一次,触发的规则总数也是8。
我错过什么了吗?我很感激你的帮助。
1条答案
按热度按时间hs1ihplo1#
当一本关于Drools的书出版的时候,它已经过时了。Drools有一些非常棒的文档,你应该把它们作为你的主要来源,而不是一本关于非常老版本的Drools的非常老的书。(Drools的当前版本是Drools 8。你的书是关于Drools 6的。)
我建议人们不要用书的另一个原因是因为书往往很糟糕,这本也不例外
你触发的规则比你想象的要多,因为“高范围订单- 10%折扣”迫使重新评估工作内存,而“为银客户创建优惠券”没有任何东西可以阻止它多次触发。
“高范围...”调用“修改”,重新触发修改项目的所有规则。由于“创建优惠券...”仍然有效,将触发两次。(它会发射一次,然后一旦“高范围......”迫使工作记忆重新评估,它会第二次被激活。)你也会看到工作记忆中的优惠券数量是你预期的两倍--将有2个优惠券而不是1个,因为您触发了优惠券规则两次。
要防止这种情况发生,您需要使“创建优惠券...”不能触发两次。(也就是说,一旦触发,就不能再次触发。)例如,您可以通过不允许两个相同的优惠券来实现此目的。或者,您可以通过只允许一个优惠券来实现此目的。具体取决于您的用例。
一种方法可能是:
在真实的世界中,你需要保持规则的简单性。不要把整个厨房Flume都放在一个KieBase中。单一责任原则是关键。你的“商品分类”规则应该与你的客户分类规则分开使用,应该与你的折扣规则分开使用。
同样调用
update
也是一个让自己陷入无限循环的好方法,并且会极大地增加内存/cpu开销。在我上一家公司,它不仅被认为是一种代码气味和不良做法,而且实际上被彻底禁止了(我们在代码评审中检查过它)