Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Rules Rules! Solving problems with business rules and declarative development Christian Parker [email protected] President, Founder, Adigio, Inc. www.adigio.com • [email protected] Copyright © 2004 Presentation Agenda In this presentation we will discuss: Thinking in Rules Solving a problem with a rules approach Declarative programming When we use rules When do you need rules? Explaining rules engines What are my options for rules engines? Rules in the Enterprise Copyright © 2004 by Adigio, Inc Solving a typical logic problem What if you had to write a program to solve this problem: A foursome of golfers is standing at a tee, in a line from left to right. Each golfer wears different colored pants: • • • • • One The Joe Bob Tom is wearing red pants golfer to Fred’s immediate right is wearing blue pants is second in line is wearing plaid pants isn’t in position one or four, and he isn’t wearing orange pants Question: In what order will the four golfers tee off, and what color are each golfer’s pants? How would you traditionally do this? Copyright © 2004 by Adigio, Inc Solving a typical logic problem Hacking the solution in Java code… … if (foo … && … || …) { if (…) { for (..) { } } } … A very hard way to solve the problem. You have to think out the entire execution path. Is there a simpler way… Copyright © 2004 by Adigio, Inc Solving a typical logic problem Using a Rules Based Approach to the solution It is easy to express the various rules for the problem ;; The golfer to Fred's right is wearing blue pants. (position (of Fred) (is ?p1)) (pants-color (of Fred) (is ?c1)) (position (of ?n&~Fred) (is ?p&:(eq ?p (+ ?p1 1)))) (pants-color (of ?n&~Fred) (is blue&~?c1)) ;; Joe is in position #2 (position (of Joe) (is ?p2&2&~?p1)) (pants-color (of Joe) (is ?c2&~?c1)) Note that we haven’t had to think through the possible execution paths to make this all work… Copyright © 2004 by Adigio, Inc ill Structured Problems When is this “rules based” way of thinking useful? Rules based solutions are perfect for Ill Structure problems An ill structured problem can not easily be solved using an algorithm, and are characterized by questions such as: Where should I travel for a fortnights holiday? What is the best price of gas? Where should I drill for oil? Copyright © 2004 by Adigio, Inc Declarative vs. Procedural What we are really talking about here, is declarative programming… Procedural languages provide a linear flow of execution, and are good for deterministic problems a step follows inevitably from the last one Declarative programs describe what the computer should do rather than the instruction on how to do it Declarative programming concerns itself with what is instead of how to. Copyright © 2004 by Adigio, Inc Comparing Declarative to Procedural Using a Rules Based Approach to the solution It is easy to express the various rules for the problem DECLARATIVE If you want to eat out, If your favorite restaurant is open, Then you should go to your favorite restaurant. If you are hungry, Then you need to eat. If your stomach is making noises, And if you've not eaten in several hours, Then you are hungry. If you need to eat, Then you want to eat out. PROCEDURAL if(person.stomachInKnot() && person.getHoursSinceEaten() > 5) { // hungry. if(time.between("12AM", "2AM") { if(person.inCity("Minneapolis") { call("burrito"); } } else if(time.before("9PM") { // ... } // ... } If you need to eat, And if it's later than 9PM Then you want to eat in. If you need to eat, And if it's between 12AM and 2AM, And if you live in Minneapolis Then call Burrito Loco for home delivery. If you buy a burrito, Then you get chips for free. Copyright © 2004 by Adigio, Inc Who uses rules? Who uses rules based approaches on a regular basis? Maybe more than you immediately think? Email Rules for Filters Spam Filters DNS routing cronjobs for scheduling Copyright © 2004 by Adigio, Inc Roadmap Where are we? Thinking in Rules When do you need rules? Incremental way of using rules from home grown to full fledged Explaining rules engines What are my options for rules engines? Rules in the Enterprise Copyright © 2004 by Adigio, Inc Contention: Missing a tool It is our contention that… The Java community doesn’t make use of rules based solutions effectively There is confusion over when to use rules engines When you get used to declarative approach, it changes the way you develop applications Copyright © 2004 by Adigio, Inc When To Use? Helps to understand how the organization deals with change Examples of dealing with change: If the business rules change, we'll release a new version Load the values from config files (SQL statements, etc.) Write change-susceptible sections in Javascript, Groovy, etc. Use plugins (the command pattern) We'll write our own rule engine No black and white criteria It's not all or nothing When you're bored and want to play with a new technology Copyright © 2004 by Adigio, Inc Rules are everywhere Business rules are everywhere! Can you spot the business rule(s)? CategoryInterest determineAgeInterest(Traveller trav) { CategoryInterest ageMatch = null; if (trav.isAdult()) { // traveller is an adult ageMatch = CategoryInterest.getCategoryInterestByValue(CategoryInterestValue.AGE_APPROPRIATE_ADULT); } else { if (trav.getAge().intValue() == -1) { // if the child's traveler's birthday is not specified, let's just pick one in the middle, 5-8 ageMatch = CategoryInterest.getCategoryInterestByValue(CategoryInterestValue.AGE_APPROPRIATE_5_8YRS); } else if (trav.getAge().intValue() >= 0 && trav.getAge().intValue() <= 4) { ageMatch = CategoryInterest.getCategoryInterestByValue(CategoryInterestValue.AGE_APPROPRIATE_0_4YRS); } else if (trav.getAge().intValue() >= 5 && trav.getAge().intValue() <= 8) { ageMatch = CategoryInterest.getCategoryInterestByValue(CategoryInterestValue.AGE_APPROPRIATE_5_8YRS); } else if (trav.getAge().intValue() >= 9 && trav.getAge().intValue() <= 13) { ageMatch = CategoryInterest.getCategoryInterestByValue(CategoryInterestValue.AGE_APPROPRIATE_9_13YRS); } else if (trav.getAge().intValue() >= 14) { ageMatch = CategoryInterest.getCategoryInterestByValue(CategoryInterestValue.AGE_APPROPRIATE_14_OLDER); } } return ageMatch; } It took me about 3 minutes to find this code from a previous project Copyright © 2004 by Adigio, Inc Example of when to use, pt1 Simple example : let's say we're building a system to analyze stock data. The customer wants a report of all stocks with a P/E ratio above 10. This should be trivial! private static final float peRatio = 10.0; ... if (stock.getPeRatio > peRatio) { // do something smart } The peRatio could be in a config file, or a DB table Later when customer says, “I've changed my mind, let's look at stocks with P/E > 8.0”, you say sure! Copyright © 2004 by Adigio, Inc Example of when to use, pt2 Things get more complex... Next, the client says, “Let's look for stocks with P/E ratio > 8.0, and price < $30” Now we have a new criteria Maybe a simple configurable SQL statement will suffice? Works if the data is in a relational DB. If DB isn't the answer we could roll our own mini rules engine We would like to 'declare' a list of criteria for the stock object. Maybe we have a simple config file like : peRatio, >, 8.0 price, <, 45 This gets a little involved. We'd have to parse this file, use reflection, etc. Hibernate has a criteria mechanism that let's you build and manage queries like this When we're done, we can handle new criteria requests from the customer. Not Bad! Copyright © 2004 by Adigio, Inc Example of when to use, pt3 This gets even more complex... The customer hits us with, let's use the above criteria, and add : If the stock is traded on Nasdaq, and today is Tuesday If the stock belongs to companies in the set (Sun, Microsoft, BEA, IBM, Adigio one day?) If the PE > 8.0 and price < 45, but not if the price is < 10 and it's 'the holliday season', etc, etc. Uh oh, we've out grown our mini rules engine Now the ability to 'declare' just about any type of rule would come in handy Even if data is in a DB, tough to write a query Copyright © 2004 by Adigio, Inc Another approach Another home rolled mini-rules engine is the command pattern: Let's say we have to find a list of products appropriate to display to an end user. We could have a configurable list of plugins (or interceptors) something like : <plugins> <class=”com.adigio.rules.BuildInitialProductPool”/> <class=”com.adigio.rules.RemoveUnderstockedProducts”/> <class=”com.adigio.rules.MatchPrice”/> <class=”com.adigio.rules.MatchType”/> <class=”com.adigio.rules.ApplyDiscounts”/> <class=”com.adigio.rules.ApplySortCriteria”/> </plugins> Here we have compartmentalized sections of rules When something has to change, it's usually easy to find where Writing and deploying new plugins could be done at runtime Could write the plugins in groovy and change them on the fly! This works well for many steps, but simple logic This doesn't solve complex if/then/else logic Copyright © 2004 by Adigio, Inc Advantages of better rule management Business policy is defined in one place Compare to how it is now all over our code! Potentially allows policy makers to define rules themselves The holy grail This doesn’t mean we are out of a job It just means that we may not get bugged as much Potentially allows you to go back and understand what the rules were in the past e.g., let's analyze this person's taxes using 1995 rules How did we handle discounts when we launched our online shopping site? Copyright © 2004 by Adigio, Inc In summary The choices of how to better manage rules aren't limited to the full blown business rules management system Many viable 'in between' solutions Understand how you need to manage change Weigh the cost of maintaining your home-grown solution If you find a lot of 40 line if then else statements it is probably time to consider better rule management Copyright © 2004 by Adigio, Inc Roadmap Where are we? Thinking in Rules When do you need rules? Explaining rules engines Rules Rule Engines Inference Engines Working memory Chaining Rules Rete Alorithm What are my options for rules engines? Rules in the Enterprise Copyright © 2004 by Adigio, Inc What is a Rule A rule has various conditions, and actions are performed if the conditions are met… Simplest form: IF conditions THEN actions Sometimes people call: conditions: predicate or premises actions: conclusions Copyright © 2004 by Adigio, Inc Rule Example A simple rule example is… RULE #1: IF Dion knows Java AND Dion knows J2EE THEN Dion knows EJB RULE #2: IF Dion knows EJB THEN Dion knows overkill technology Copyright © 2004 by Adigio, Inc Rule Example Rules have linkage… RULE #1: IF Dion knows Java AND Dion knows J2EE THEN Dion knows EJB RULE #2: IF Dion knows EJB THEN Dion knows overkill technology It is important that rule actions can cause other rules to fire! Copyright © 2004 by Adigio, Inc What is a Rule Engine? A glorified State Machine? High level view: Starts with facts Apply rules Derive more facts … apply more rules Copyright © 2004 by Adigio, Inc Forward vs. Backward Chaining Application areas Backward Chaining Forward Chaining 1. Working memory contains facts (like Dion knows J2EE) 2. Find a rule where the ‘if’ part is satisfied by facts in working memory 3. Fire rule, and add any facts generated by the ‘then’ part 4. repeat until no rules have satisfied if parts Few rules, then chain forward Few facts, then chain backward Copyright © 2004 by Adigio, Inc 1. Start with a hypothesis (like Dion knows Overkill technology.) 2. find which rules satisfy the goal, create necessary sub-goals as needed. 3. query facts to see if rules can be satisfied How does a rule engine do its work? Rete Algorithm There are various algorithms to power a rules engine. The most common is called the Rete algorithm The Rete algorithm creates a network graph: The matching is a repeating process Fact list changes each cycle Rules are stable, facts change Rete remembers past test results Copyright © 2004 by Adigio, Inc Roadmap Where are we? Thinking in Rules When do you need rules? Explaining rules engines What are my options for rules engines? Drools Jess Mandarax JRules JSR 94 Rules in the Enterprise Copyright © 2004 by Adigio, Inc Rules Engines in Java We are lucky in that there is a wealth of choice in the Java space Open Source: Drools (http://drools.codehaus.org): Codehaus based OO Java implementation of Rete (ASL based license) Jess (http://herzberg.ca.sandia.gov/jess): CLIPS-esque based Java implementation (dual academic/commercial licenses) Mandarax (http://mandarax.sourceforge.net): OO Java implementation of a backwards chaining engine (LGPL based license) Commercial: ILOG JRules Fair Isaac Blaze Advisor Oracle Rules (based on Jess) And many, many more (40+ listed on www.javarules.org) Copyright © 2004 by Adigio, Inc Using Drools Overview Basic steps in Drools In Java, load rules file Create a org.drools.RuleBase from the rules file Create a org.drools.WorkingMemory from the RuleBase Assert facts on WorkingMemory, which builds a rule agenda Fire rules, i.e. execute the agenda, which manipulates facts, changes state Copyright © 2004 by Adigio, Inc Drools Example: Java Simple java example that loads and executes drools rules // (1) load the rules file URL url = this.getClass().getClassLoader().getResource(rulesFileName); if (url == null) { throw new RuntimeException("URL not found for filename " + this.rulesFileName); } // (2) create an org.drools.RuleBase from the file RuleBase ruleBase = RuleBaseLoader.loadFromUrl(url); // (3) build an org.drools.WorkingMemory from the rule base WorkingMemory wm = ruleBase.newWorkingMemory(); // (4) assert objects willy nilly wm.assertObject(foo); wm.assertObject(bar); // (5) get a handle on a result context RulesResultContext ctx = new RulesResultContext(); // (6) fire away wm.fireAllRules(); Copyright © 2004 by Adigio, Inc Drools Example: Rules File The structure of a single rule is one or more parameters, one or more conditions, and a single consequence <rule-set name="cheese rules" xmlns="http://drools.org/rules" xmlns:java="http://drools.org/semantics/java"> (1) <rule name="Bob Likes Cheese"> (2) <parameter identifier="bob"> <java:class>org.drools.examples.simple.Bob</java:class> </parameter> (3) <java:condition>bob.likesCheese() == true</java:condition> (4) <java:consequence> System.out.println( "Bob likes cheese." ); </java:consequence> </rule> </rule-set> This simple example has one rule named “Bob Likes Cheese” The rule looks in working memory instances of Bob objects (facts) For each Bob in the working memory that likes cheese, the consequence will execute Copyright © 2004 by Adigio, Inc Drools Semantic Modules Drools has interchangeable semantic modules The example uses the Java semantic module This means the condition and consequence sections contain java code Drools includes semantic modules for Java, Groovy, and Python You could implement your own semantic module to create a domain-specific language <rule-set name="cheese rules" xmlns="http://drools.org/rules" xmlns:java="http://drools.org/semantics/java"> <rule name="Bob Likes Cheese"> <parameter identifier="bob"> <java:class>org.drools.examples.simple.Bob</java:class> </parameter> <java:condition>bob.likesCheese() == true</java:condition> <java:consequence> System.out.println( "Bob likes cheese." ); </java:consequence> </rule> </rule-set> Copyright © 2004 by Adigio, Inc Drools: Comparing Java / Groovy <rule name="Explode Cart" salience="20"> <parameter identifier="cart"> <class>org.drools.examples.petstore.ShoppingCart</class> </parameter> <java:condition>cart.getState( "Exploded" ) == false</java:condition> <java:consequence> import java.util.Iterator; System.out.println( "Examining each item in the shopping cart." ); Iterator itemIter = cart.getItems().iterator(); while ( itemIter.hasNext() ) { drools.assertObject( itemIter.next() ); } cart.setState( "Exploded", true); drools.modifyObject( cart ); </java:consequence> <!-- assert each item in the shopping cart into the Working Memory --> </rule> <rule name="Explode Cart" salience="20"> <parameter identifier="cart"> <class>org.drools.examples.petstore.ShoppingCart</class> </parameter> <groovy:condition>cart.getState( "Exploded" ) == false</groovy:condition> <groovy:consequence> println "Examining each item in the shopping cart." ; cart.getItems().each { item | drools.assertObject( item ) } ; cart.setState( "Exploded", true); drools.modifyObject( cart ); </groovy:consequence> </rule> Copyright © 2004 by Adigio, Inc Drools Points of Interest Gotcha: Facts can be manipulated by consequences Watch out for infinite recursion when doing this : <rule name="example rule"> <parameter identifier="s"> <java:class>State</java:class> </parameter> <java:condition>s.getState() == true</java:condition> <java:consequence> s.setState(true); drools.modifyObject(s); </java:consequence> </rule> Copyright © 2004 by Adigio, Inc Drools Summary Fairly simple, easy to bring into an existing Java project Rules can be written in Java no need to learn a new language Drools is a engine only It has no concept of managing rules, versioning, loading, etc Documentation is good, and seems to be improving No book yet (anyone interested? ) It's free :) Copyright © 2004 by Adigio, Inc Using Jess Overview Let’s dive into Jess a little… Jess == Java Expert System Shell Written in Java easy to embed and use in Java applications Clone of CLIPS lisp-like expert system The Jess language is very lisp-like (deftemplate combination (slot letter (type ATOM)) (slot number (type INTEGER))) Copyright © 2004 by Adigio, Inc Sample Jess Language Sample Jess Language ;; Define a shadow fact (defclass chart ShoppingChart) ;; Create a new chart (bind ?chart (new ShoppingChart)) ;; Bind instance to fact (definstance ?c chart) ;; Set the value of the chart (call ?c setValue 1000) ;; Writing a rule (def rule discount-rule ;; if chart value > 1000 then apply the discount (chart (value ?v&:(> ?v 1000))) => (call ?c setDiscount 15)) Copyright © 2004 by Adigio, Inc Calling Jess from Java This is how you can call out to Jess from Java code: // Setup local variables Customer customer; ShoppingChart chart; Item item; // Setup the rules engine Rete engine = new Rete(); engine.store(“customer”, customer); engine.store(“chart”, chart); engine.store(“item”, item); String ruleSet = read(“chart-rules.clp”); engine.executeCommand(ruleSet); engine.run(); Copyright © 2004 by Adigio, Inc Jess Summary Oldest, most mature, open source rules engine Based on CLIPS (very old and proven expert system) Jess language is very different ((Get (ready to learn) some LISP) baybee ) Documentation is very solid Website docs Jess In Action Author is a professor who gets this stuff Licensing is a little strange (dual licensing) Trial editions run out of time Copyright © 2004 by Adigio, Inc Using Mandarax Overview Mandarax is an LGPL solution Based on backwards reasoning (not RETE) Includes a library of pre-defined predicates and functions Supports RuleML Includes Oryx Rule management tool Repository for managing the vocabulary Natural language based rule editor Copyright © 2004 by Adigio, Inc Using ILog JRules Overview JRules is a commercial suite (more than a rules engine) Written in Java Two styles of language Basic rule language when { ?c:ShoppingChart(value > 1000); } then { ?c.setDiscount(15); } Business action language (english ) IF the shopping chart value is greater than 1000 THEN apply a 15% discount Copyright © 2004 by Adigio, Inc JSR 94: Standardization JSR 94 is The Java Rule Engine API javax.rules.* GOAL: To provide a common interface for integration of Rules engines in Java programs Only deals with getting handles to rule engines, NO standard for the rule language etc… This isn’t an API for cross platform rules Copyright © 2004 by Adigio, Inc JSR 94: Using it in code Here is how you get access via JSR 94: // Imports import javax.rules.*; import javax.rules.admin.*; // Import the driver that you want to use, e.g. Drools import org.drools.jsr94.rules.RuleServiceProviderImpl; // Register the driver RuleServiceProviderManager.registerRuleServiceProvider( RULE_SERVICE_PROVIDER, RuleServiceProviderImpl.class); RuleServiceProvider ruleServiceProvider = RuleServiceProviderManager.getRuleServiceProvider( RULE_SERVICE_PROVIDER ); // Load the rule admin ruleAdministrator = ruleServiceProvider.getRuleAdministrator( ); // Load the rules and register them LocalRuleExecutionSetProvider ruleSetProvider = ruleAdministrator.getLocalRuleExecutionSetProvider( null ); InputStream rules = this.getClass( ).getResourceAsStream( ruleUri ); RuleExecutionSet ruleExecutionSet = ruleSetProvider.createRuleExecutionSet( rules, null ); ruleAdministrator.registerRuleExecutionSet( ruleUri, ruleExecutionSet, null ); Copyright © 2004 by Adigio, Inc JSR 94: Integrating with Spring Spring has nice clean JSR 94 integration so you don’t have to mess with a lot of code to access your rules engine There are a set of configuration steps to allow Spring to administer and use rules engines Declare a RuleServiceProvider Declare a RuleAdministor Declare a RuleRuntime Define a ruleset <bean id="ruleServiceProvider" class="org.springmodules.jsr94.factory.DefaultRuleServ iceProviderFactoryBean"> <property name="provider"> <value>org.jcp.jsr94.jess</value> </property> <property name="providerClass"> <value>org.jcp.jsr94.jess.RuleServiceProviderImpl</val ue> </property> </bean> This is all boilerplate <bean> XML in Springs config file! Copyright © 2004 by Adigio, Inc Roadmap Where are we? Thinking in Rules When do you need rules? Explaining rules engines What are my options for rules engines? Rules in the Enterprise Business Rule Management System Workflow BPM BPEL Copyright © 2004 by Adigio, Inc Rules for the Enterprise Large enterprise projects need more than just the rules engine itself This is where a Business Rule Management System comes into play A set of tools and processes that facilitate the communication, deployment, and execution of business policy within an IT infrastructure Copyright © 2004 by Adigio, Inc Business Rule Management A BRMS contains: Rich client editor for business rules Potentially used by business types Web interface Central rule repository (version controlled) Hot deployment of rules Rule debugger Rule engine Business Reporting Runtime monitoring Copyright © 2004 by Adigio, Inc Business Rule Management An advanced BRMS contains: Dynamic runtime reporting Rule refactoring and analysis Business simulation and testing framework Collaboration features: Security, policy, permissions, locking Branching and merging rules Dynamic healing and rule changing Defining domain specific languages for rules and processes Copyright © 2004 by Adigio, Inc Other similar technologies… There are other technologies which are similar… Workflow Workflow helps you automate a range of business tasks, and electronically route the right information to the right people at the right time. Users are notified of pending work, and help managers route approvals through the system quickly. BPM “an integrated management approach that includes Web-based analytical applications (to gather and analyze data), business plans to achieve desired metrics and the necessary reporting and forecasting to ensure performance goals.” BPEL / BPEL4J / BPELWS All about defining process Does not directly support abstractions for people, roles, work items or inboxes/queues, hence BPEL is not equivalent to workflow Does not specify a data model for process reporting, analysis or monitoring/administration, hence BPEL is not equivalent to BPM Copyright © 2004 by Adigio, Inc Module Summary In this module we discussed: “Thinking in Rules” What declarative programming is good for The ideas behind rules engines and rules How engines work How to work with rules Jess Drools Mandarax Spring support Rules in the enterprise Copyright © 2004 by Adigio, Inc Resources Find information at the following web sites Java Rules http://www.javarules.org/ Jess http://herzberg.ca.sandia.gov/jess/ Drools http://drools.org/ Mandarax http://www.mandarax.org/ JSR 94 http://www.jcp.org/en/jsr/detail?id=94 Copyright © 2004 by Adigio, Inc