Reputation: 370
I'm new to drools and I've written some rules and they work as expected. However, I can't help but think there is a more concise way of writing these rules.
My situation is that many of the rules have a few similar basic requirements that I'm repeating in each rule. So, for instance, suppose I have the following rules:
rule "Main Valid Message"
when Account (open && valid)
then myResults.add(new Message("Your account is valid"))
end
rule "The user owns something Message"
when Account (ownership.size() >= 1)
then myResults.add(new Message("You own something"))
end
rule "Eligibility Message"
when
Account (open && valid)
Account (ownership.size() >= 1)
then myResults.add(new Message("You are eligible"))
end
Is there a way to rewrite the eligibility rule to take advantage of the first two rules instead of duplicating their content?
ANSWER: Using a combination of J Andy's and laune's replies below, I wrote it as follows:
declare IsValid
account : Account
end
declare OwnsSomething
account : Account
end
rule "Main Valid Message"
when $account : Account (open && valid)
then
myResults.add(new Message("Your account is valid"))
insertLogical(new IsValid($account));
end
rule "The user owns something Message"
when $account : Account (ownership.sizeOwnsSomething() >= 1)
then
myResults.add(new Message("You own something"))
insertLogical(new OwnsSomething($account));
end
rule "Eligibility Message"
when
IsValid()
OwnsSomething()
then myResults.add(new Message("You are eligible"))
end
Upvotes: 4
Views: 3625
Reputation: 31290
Then there is the possibility of extending a rule, which lets you inherit the conditions of one rule to any number of other rules:
rule "multiple account owners"
when
$acc: Account( owners.size() > 1 )
then end
rule "multiple and open and valid"
extends "multiple account owners"
when
Account( this == $acc, open && valid )
then
If you follow Andy's idea, consider using insertLogical and a reference to the Account in question (unless you're investigating one Account fact at a time):
rule "multiple account owners"
when
$acc: Account( owners.size() > 1 )
then
insertLogical( new Multiple( $acc ) );
end
Be careful with this approach so as not to have rules fire prematurely with the negated (!) form of the property represented by the auxiliary fact, e.g.,
rule "funny account"
when
$acc : Account( balance > 10000000 ) # can have more than one owner
not Multiple( account == $acc )
then ... end
This can fire before "multiple account owners" asserts Multiple, unless that rule is given a higher salience. Also, be aware of the effect of evaluating all of these properties by inserting auxiliary facts: this overhead is created anyway, even if a certain Account will not need them all in order to be processed.
Finally, there's the idea of an Adapter (or wrapper) for Account providing any number of fancy getters for Account:
rule "wrap account"
when $acc: Account() not Wrapper( account == $acc )
then insert( new Wrapper( $acc ) end
rule "multiple valid-open"
when Wrapper( multiple && validOpen )
then ... end
And you may, of course, resort to DRL functions:
function boolean multiOwners( Account account ){
return account.getOwners().size() > 1;
}
rule "multi valid open"
when $acc: Account( eval( multiOwners($acc) && openValied($acc) ) )
then ... end
(I'm not sure whether you need the eval in the latest Drools version(s).)
Upvotes: 3
Reputation: 4823
One option would be to use (internal) facts to handle state. Something like this
declare AuthenticatedUser
end
rule "Authenticate user"
when
Account( open && valid )
then
insert( new AuthenticatedUser() );
end
rule "Eligibility Message"
when
AuthenticatedUser()
then
myResults.add( new Message( "You are eligible" ) );
end
I'm not sure what's your use case for Account ownership, but I think you'll get the point from the above code sample.
The AuthenticatedUser
fact is now declared inside the DRL file. It could just as well be normal Java class. Also, in the example it has no properties at all, but as mentioned earlier, it could even hold some state as well which you modify in the rules.
Upvotes: 1