Search code examples
drools

How to handle lots of rules with shared conditions in Drools


Let's supposed I'm working on a sales tax calculation application that has lots of rules for each of the states; e.g., I might have

rule "Florida Food Sales Tax"
   when
      $item : OrderItem( state == States.FL, category == Categories.FOOD )
   then
      modify($item) { setSalesTax(new BigDecimal("5") }
end

rule "Florida Non-Food Sales Tax"
   when
      $item : OrderItem( state == States.FL, category == Categories.NONFOOD )
   then
      modify($item) { setSalesTax(new BigDecimal("8") }
end

In this application I might have dozens, even hundreds of rules about Florida sales tax...and for every one of the other states as well. It gets tedious having to put the state condition in every rule. Is there a way to create some kind of nested context around rules so I only have to do that once for a whole block? Something like (and I know this isn't valid, consider this pseudo-code):

when $item : OrderItem( state == States.FL )
   rule "Florida Food Sales Tax"
       when
          $item : OrderItem( category == Categories.FOOD )
       then
          modify($item) { setSalesTax(new BigDecimal("5") }
   end
   .
   .
   .
end

I know rules can extend other rules, but as far as I can tell they can only have one parent and I might want to split things up into multiple blocks; e.g., have sub-blocks for the food vs. non-food rules.


Solution

  • Extending rules can be continued over more than one level so that you could have a parent rule

    rule "Florida Sales Tax"
    when
        $florida: OrderItem( state == States.FL )
    then end
    

    and at the next level two rules for food and non-food with a couple of rules like this one:

    rule "Florida Food Sales Tax" extends "Florida Sales Tax"
    when
        $ffi: OrderItem( this == $florida, category == Categories.FOOD )
    then end
    

    Equally well, you could start the hierarchy by selecting the category first, but there's no way to inherit from more than one rule. (Besides, I doubt that the gain would be worth doing it.)

    Note that you'll run into the same dilemma when using a decision table. Joining cells with the same value for a property is only possible if the resulting rules are placed next to each other - and you can't do this for all rules for more than one property at the same time.