- We design and build extraordinary applications for companies looking to make the next great idea a reality.
- learn more
BRE Patterns III: Collaboration Cop, Part II
In explaining this pattern, I wanted to take a step back and explain where and how OO and BRE's intersect. To start with, this excellent post over at Mark Proctor's blog makes the following statement:
Assert all your objects as facts: Rule engines usually know how to handle a fairly heavy load of facts, so let the engine do its magic. If you want to reason over a nested set of objects, assert all of them (not only the top level ones) into the engine and make sure your business model models the relationship between them. After that, writing your rules will be easier and the engine will be able to optimize execution (when compared to using eval and other constructs to access deeply nested structures). Example: if you have an Order fact that contains a list of OrderItems, assert both Order and OrdemItems as facts (if you need to reason over OrderItems too, obviously).
Why, by all that is object oriented, do you have to turn your domain model inside out, exposing what was hidden, unencapsulating what was encapsulated? Isn't this defeating the purpose of object orientation? The answer is, in short, yes. You are defeating the purpose of OO when you expose the innards of your model to the BRE. But it is a tradeoff. You get something for your trouble. Specifically, you get the super efficient rule matching of RETE and it's decendents.
This sort of exploding of the object model happens all the time in systems, and it isn't necessarily always bad. Alen Hollub (author of Why getter and setter methods are evil and other Edsger Dijkstra-like articles) has identified the "procedural boundary layer" and explains it nicely in his book Holub on Patterns: Learning Design Patterns by Looking at Code:
One big exception exists to the no-getter-or-setter rule. I think of all OO systems as having a "procedural boundary layer." The vast majority of OO programs run on procedural operating systems and talk to procedural databases, for example. The interfaces to these external procedural subsystems are by their nature generic. The designer of JDBC hasn't a clue about what you'll be doing with the database, so the class design has to be unfocused and highly flexible. UI-builder classes such as Java's Swing library are another example of a "boundary-layer" library. The designers of Swing can't have any idea about how their classes will be used; they're too generic. Normally, it would be a bad thing to build lots of flexibility that you didn't use because it increases development time. Nonetheless, the extra flexibility is unavoidable in these boundary APIs, so the boundary-layer classes are loaded with accessor and mutator methods. The designers really have no choice.
BRE's are not OO. Yes, the facts can be viewed as objects and the BRE's can be implemented using and OO language and design, but really the internal working of the BRE are most definitely not OO, the more the rule engine knows about each and every object and its innards, the more efficient it can be. Thus the PBL (procedural boundary layer) applies.
As an example why you need to expose all object, consider an order that is made up of line items.
public interface Order {
[...]
void addItem(OrderLineItem item);
boolean removeItem(OrderLineItem item);
[...]
}
Now normally you would hide the details of all the line items inside the class that implements the Order interface. Let's suppose now that we haven't added any of the encapsulated line items to the working memory of the BRE's, just the order. Now let's say we update one of the line items through an operation. The only way we have to telling the BRE that something has changes is by flagging the enclosing Order object. That will trigger a reevaluation of every rule in which the Order plays a part, even ones where the line items play no part.
There are all sorts of ways of dealing with exposing the internals of your domain model to the BRE without breaking encapsulation. One way is to implement both the business interface and a bean interface (getters, setters, etc.) in the implementation (see diagram). The business interface is used within the domain model, the bean interface in the BRE.
Another approach is to wrap the domain objects in bean containers that access the private instance variables through reflection.
Of course lots of this depends on the specific BRE you are using. Some require you to expose your instance variables directly and don't deal well with method calls. I'd suggest not using those.
Next time I'll go through a simple example using JBoss Rules showing how to convert a domain model to a Collaboration Cop rule base.
Topics: Business Rules, Patterns
Comments: 2 so far
Leave a comment
About Pathfinder
Recent
- Firefox Plugin Malware ‘Trojan.PWS.ChromeInject.A’
- Pathfinder releases version 1 of the its Flash Platform microsite (codename Mica)
- Pimp my Rails: Five Plugins & Gems to Make Rails Better
- iPhone: Using Pre-processor Directives for Device Testing
- Subtle OpenGL Projection Matrix Difference Between iPhone Simulator and Device
- App Security: Throw Out the Org Chart!
- Pimp my jQuery: Five plugins to replace the features Prototype and Scriptaculous users expect
- Thanksgiving 2008: What We’re Thankful For (In Rails)
- iPhone SDK: Testing with TextMate & GTM
- GWTQuery - JQuery-like Syntax in GWT
Archives
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- March 2007
- February 2007
- January 2007
- December 2006
- November 2006
- October 2006
- September 2006
- August 2006
- July 2006
- June 2006
- May 2006
- April 2006
- March 2006



To make the most of objects you need to express your nested objects as relationships. Take Conways Game of Life example. When it was contributed to us all the neighbor cells for a particular cell where stored in a HashSet as a private member, this meant the engine had no way to reason over it - so all the processing and calculation logic was in java. So I created Neighbour class to express this relationship which is actually more clear and declarative than a nested HashSet, I was then also able to exploit the cross product of this relation to drive the main application. Interestingly this is how things are going with the semantic web, properties become relations instead of meaningless private members.
Mark
http://markproctor.com/
Comment by Mark Proctor, Sunday, May 13, 2007 @ 9:03 am
The stock has gained 150% from Oct 8, 2007 to Oct 22, 2007.
By the way check this company MDFI. Their stock is set to increase because of their association with Apple iphone and Complete Care Medical. Find more about this company and stock http://www.growurmoney.com/medefile/
Comment by prakash, Monday, November 12, 2007 @ 11:51 pm