Specification Pattern and Boolean Operator Precedence
Posted
by Anders Nielsen
on Stack Overflow
See other posts from Stack Overflow
or by Anders Nielsen
Published on 2010-04-14T12:28:44Z
Indexed on
2010/04/14
12:43 UTC
Read the original article
Hit count: 411
In our project, we have implemented the Specification Pattern with boolean operators (see DDD p 274), like so:
public abstract class Rule { public Rule and(Rule rule) { return new AndRule(this, rule); } public Rule or(Rule rule) { return new OrRule(this, rule); } public Rule not() { return new NotRule(this); } public abstract boolean isSatisfied(T obj); } class AndRule extends Rule { private Rule one; private Rule two; AndRule(Rule one, Rule two) { this.one = one; this.two = two; } public boolean isSatisfied(T obj) { return one.isSatisfied(obj) && two.isSatisfied(obj); } } class OrRule extends Rule { private Rule one; private Rule two; OrRule(Rule one, Rule two) { this.one = one; this.two = two; } public boolean isSatisfied(T obj) { return one.isSatisfied(obj) || two.isSatisfied(obj); } } class NotRule extends Rule { private Rule rule; NotRule(Rule obj) { this.rule = obj; } public boolean isSatisfied(T obj) { return !rule.isSatisfied(obj); } }
Which permits a nice expressiveness of the rules using method-chaining, but it doesn't support the standard operator precedence rules of which can lead to subtle errors.
The following rules are not equivalent:
Rule<Car> isNiceCar = isRed.and(isConvertible).or(isFerrari); Rule<Car> isNiceCar2 = isFerrari.or(isRed).and(isConvertible);
The rule isNiceCar2 is not satisfied if the car is not a convertible, which can be confusing since if they were booleans
isRed && isConvertible || isFerrariwould be equivalent to
isFerrari || isRed && isConvertible
I realize that they would be equivalent if we rewrote isNiceCar2 to be isFerrari.or(isRed.and(isConvertible)), but both are syntactically correct.
The best solution we can come up with, is to outlaw the method-chaining, and use constructors instead:
OR(isFerrari, AND(isConvertible, isRed))
Does anyone have a better suggestion?
© Stack Overflow or respective owner