• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Brms best practices_2011_oct_final
 

Brms best practices_2011_oct_final

on

  • 1,969 views

 

Statistics

Views

Total Views
1,969
Views on SlideShare
1,969
Embed Views
0

Actions

Likes
4
Downloads
104
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Brms best practices_2011_oct_final Brms best practices_2011_oct_final Presentation Transcript

    • BRMS: Best (and worst) Practices and Real World Examples Edson Tirelli Senior Software Engineer JBoss, by Red Hat1 Rules Fest – October 2011
    • It all starts with a question... What is the performance of <BRMS product name>?2 Rules Fest – October 2011
    • Followed by... Are there any best practices (a.k.a blue prints) to achieve performance <X>?3 Rules Fest – October 2011
    • Lets talk about blue prints... ... but first, lets open our eyes to everything rules engines have to offer us!4 Rules Fest – October 2011
    • BRMS adoption goals5 Rules Fest – October 2011
    • A simple analogy Business Rules Engines Databases (Rules) (Data)6 Rules Fest – October 2011
    • BRMS: goals ● Independent Lifecycle Management of Business Rules7 Rules Fest – October 2011
    • BRMS: goals ● Declarative language for rules and queries ● Focus on “what to do”, not “how to do it” rule “Send shipment pick-up SMS alert” rule “Send shipment pick-up SMS alert” when when There is a shipment order There is a shipment order There is a route assigned to the order There is a route assigned to the order There is a truck GPS reading and the truck is 15m from the pick-up location There is a truck GPS reading and the truck is 15m from the pick-up location then then Send SMS to customer: ARRIVING, “15 minutes” Send SMS to customer: ARRIVING, “15 minutes” end end8 Rules Fest – October 2011
    • BRMS: goals ● Logic, Data and Tasks split ● Centralization of Knowledge ● Consistency ● Testing / Simulation Knowledge Knowledge Base Session ● Auditing (production Inference (working memory/ Engine memory/ ● Explanation Facility rules) facts/data) * Directly or Indirectly Tasks (services, procedures, etc)9 Rules Fest – October 2011
    • BRMS: goals ● Execution Performance and Scalability ● Many-to-many pattern matching algorithm ● Optimizes the whole set of rules ● Performance is linear on the number of rules “touched” by each fact ● Easily scales to tens of thousands of rules ● Eager evaluation with incremental changes re-evaluation10 Rules Fest – October 2011
    • Under the hood11 Rules Fest – October 2011
    • Rete in 30 seconds ● Classic Rete algorithm “idea” ● Discrimination network ● Facts arrive at the top Fact Types ● Propagate down ● If they reach the bottom, Filter conditions (alpha network) corresponding rule activates ● + Enables optimizations ● + Enables additional feature set Join conditions (beta network) Rules12 Rules Fest – October 2011
    • Typical Rete Optimizations ● Support to POJOs as facts ● no mapping/data copy necessary ● Full split between KBase and Working Memory ● lightweight session creation ● knowledge base sharing ● Completely Dynamic KBase management ● Hot addition/removal/updates of rules/queries/processes ● Full support to First Order Logic and Set operations ● JIT compilation for constraints and data access13 Rules Fest – October 2011
    • Typical Rete Optimizations ● Node Sharing (constraint sharing) ● Alpha Hashing: ● Provides O(1) performance for mutually exclusive constraints ● Rule 1: Customer is GOLD ● Rule 2: Customer is SILVER Uses a hash function instead of ● Rule 3: Customer is BRONZE checking each constraint ● Rule x: Customer is XYZ14 Rules Fest – October 2011
    • Typical Rete Optimizations ● Beta Memory Indexing: ● Provides O(1) performance for joins Order( customerId == $someCustomer.id ) ● FOL lazy match: ● Avoids wasted matching on FOL conditional elements exists( Customer( age > 50 ) )15 Rules Fest – October 2011
    • Typical Rete Optimizations: Visual Index Class type caching (+ inheritance support) Fact Types Node Sharing Filter conditions Alpha Hashing (alpha network) FOL Lazy match Join conditions Memory Indexing (beta network) Aggregations/Accumulations Rules16 Rules Fest – October 2011
    • Best Practices17 Rules Fest – October 2011
    • BRMS Best Practices ● Dont try to micro-control rules execution ● Use the Conflict Resolution Strategies instead ● Salience ● Agenda groups ● Ruleflow ● Dynamic enablement Knowledge Knowledge Base Session (production Inference (working memory/ Engine memory/ rules) facts/data) Tasks (services, procedures, etc)18 Rules Fest – October 2011
    • BRMS Best Practices ● Partition your Knowledge Bases properly ● Subject matter ● Transaction / Service / Unit of Work ● Business Entity ● Avoid monolithic kbases ● Avoid fine grained kbases Knowledge Knowledge Base Session (production Inference (working memory/ Engine memory/ rules) facts/data) Tasks (services, procedures, etc)19 Rules Fest – October 2011
    • BRMS Best Practices ● Cache the Knowledge Base, share the sessions ● Rules are usually JIT compiled at load time ● Can be compiled at build time for non-dynamic use cases Knowledge Knowledge Base Session (production Inference (working memory/ Engine memory/ rules) facts/data) Tasks (services, procedures, etc)20 Rules Fest – October 2011
    • BRMS Best Practices ● Dont overload rules ● Each rule should describe one and only one scenario→action mapping ● The engine will optimize shared conditions ● The engine supports inference rule “Short sale” rule “Short sale” rule “Refuse short sales” rule “Refuse short sales” when when when when $ss : SecuritySaleOrder() $ss : SecuritySaleOrder() $ss : SecuritySaleOrder() $ss : SecuritySaleOrder() not( Security( this == $ss.security ) ) not( Security( this == $ss.security ) ) exists( ShortSale( this.ss == $ss ) ) exists( ShortSale( this.ss == $ss ) ) then then then then // identify as a short sale // identify as a short sale // refuse order // refuse order insert( new ShortSale( $ss ) ); insert( new ShortSale( $ss ) ); $ss.refuse(); $ss.refuse(); end end end end21 Rules Fest – October 2011
    • BRMS Best Practices ● Avoid the use of “evals” ● Harder for the engine to optimize ● Harder for rule authors to maintain ● Use engine features: ● Pluggable operators ● Annotations ● ... rule “Simultaneous calls from different places” rule “Simultaneous calls from different places” @system( “Fraud Detection” ) @requirementId( “FD001” ) @system( “Fraud Detection” ) @requirementId( “FD001” ) when when $c1 : VoiceCall() $c1 : VoiceCall() $c2 : VoiceCall( cust == $c1.cust, base != $c1.base, $c2 : VoiceCall( cust == $c1.cust, base != $c1.base, base notAdjancent $c1.base ) base notAdjancent $c1.base ) then then // possible fraud detected // possible fraud detected end end22 Rules Fest – October 2011
    • BRMS Best Practices ● Batch data loads ● It is usually faster to load 1000 facts and then fire the rules than fire rules after each inserted fact ● Partition the data into multiple sessions ● Transaction / Service / Unit of work ● Creating a new session is cheap Knowledge Knowledge ● Sometimes cheaper than Base (production Inference Session (working memory/ Engine memory/ removing facts from existing rules) facts/data) session. Tasks (services, procedures, etc)23 Rules Fest – October 2011
    • BRMS Best Practices ● Quality of the data/fact model is directly proportional to the performance and maintainability of the rules using it ● Think about the DBMS analogy ● Flatter models improve performance ● Smaller classes help avoiding recursions Knowledge Knowledge Base Session (production Inference (working memory/ Engine memory/ rules) facts/data) Tasks (services, procedures, etc)24 Rules Fest – October 2011
    • Best Practices in Rules Authoring25 Rules Fest – October 2011
    • A Frog Rule: anything odd about it? rule “11111” rule “11111” # NOTE: Please note that this rule is associated with rule #22222. If you make any changes in # NOTE: Please note that this rule is associated with rule #22222. If you make any changes in # its logic, please do the same for rule #22222 # its logic, please do the same for rule #22222 when when # RULE CHANNEL MANDATORY SECTION # RULE CHANNEL MANDATORY SECTION ControlFact( a[“11111”].b[this.X].enabled == true, a[“11111”].s[this.S] == true ) ControlFact( a[“11111”].b[this.X].enabled == true, a[“11111”].s[this.S] == true ) # BUSINESS LOGIC # BUSINESS LOGIC Frog( color == “green” ) and Frog( color == “green” ) and ( #rule 22222 ( #rule 22222 Frog( eval( height.bigDecimalValue.compareTo( somePrince.height.bigDecimalValue ) > 0 ) ) Frog( eval( height.bigDecimalValue.compareTo( somePrince.height.bigDecimalValue ) > 0 ) ) ) || ( #rule 33333 ) || ( #rule 33333 Prince( name == “Charming”) Prince( name == “Charming”) ) || ( #rule 44444 ) || ( #rule 44444 ... ... ) ) then then // An empty “consequence” // An empty “consequence” end end PS: lets focus on the structure of the rule and not the actual logic.26 Rules Fest – October 2011
    • A Frog Rule: looks suspicious Rule name as part of the logic? rule “11111” rule “11111” # NOTE: Please note that this rule is associated with rule #22222. If you make any changes in # NOTE: Please note that this rule is associated with rule #22222. If you make any changes in # its logic, please do the same for rule #22222 # its logic, please do the same for rule #22222 when when # RULE CHANNEL MANDATORY SECTION # RULE CHANNEL MANDATORY SECTION ControlFact( a[“11111”].b[this.X].enabled == true, a[“11111”].s[this.S] == true ) ControlFact( a[“11111”].b[this.X].enabled == true, a[“11111”].s[this.S] == true ) # BUSINESS LOGIC # BUSINESS LOGIC Use of control fact? Frog( color == “green” ) and Frog( color == “green” ) and ( #rule 22222 ( #rule 22222 Frog( eval( height.bigDecimalValue.compareTo( somePrince.height.bigDecimalValue ) < 0 ) ) Frog( eval( height.bigDecimalValue.compareTo( somePrince.height.bigDecimalValue ) < 0 ) ) ) || ( #rule 33333 ) || ( #rule 33333 “Embedded” rules? Prince( name == “Charming”) Prince( name == “Charming”) ) || ( #rule 44444 ) || ( #rule 44444 Over use of evals? ... ... ) ) then then // An empty “consequence” Empty consequence? // An empty “consequence” end end27 Rules Fest – October 2011
    • Why is an empty consequence bad? rule “11111” rule “11111” when when ... ... then then // An empty “consequence” // An empty “consequence” end end Breaks independent lifecycle management goal Breaks centralization of knowledge goal Breaks clarity goal (what to do?) Breaks explanation facility goal The Frog will never turn into a Prince Should this be a query instead?28 Rules Fest – October 2011
    • Alternatives: Rules vs Queries Rules Queries Control Invoked by the engine Invoked by the application Parameters Dont support parameters Support parameters Results Execute actions Return results rule “Transform Frog into Prince” rule “Transform Frog into Prince” when when $f : Frog( color == “green” ) $f : Frog( color == “green” ) then then insert( new Prince( “Mark” ) ); insert( new Prince( “Mark” ) ); retract( $f ); retract( $f ); end end query “Get the frog”( $color ) query “Get the frog”( $color ) when when $f : Frog( color == $color ) $f : Frog( color == $color ) end end29 Rules Fest – October 2011
    • Why is bad to use the rule name inthe logic? rule “11111” rule “11111” when when ControlFact( a[“11111”].b[this.X].enabled == true, a[“11111”].s[this.S] == true ) ControlFact( a[“11111”].b[this.X].enabled == true, a[“11111”].s[this.S] == true ) ... ... ( #rule 22222 ( #rule 22222 ... ... Breaks clarity goal Breaks “one scenario – one action” best practice Rule names must be unique within the knowledge base Usually leads to micro-control and procedural code30 Rules Fest – October 2011
    • Alternatives for metadata declaration rule “11111 – transform the frog into a prince” rule “11111 – transform the frog into a prince” @requirementId( “11111” ) @author( “Mark” ) @requirementId( “11111” ) @author( “Mark” ) @relatedTo( “22222, 33333” ) @relatedTo( “22222, 33333” ) @documentation( “A rule with lots of annotations” ) @documentation( “A rule with lots of annotations” ) when when ... ... then then insert( new Prince( “Mark” ) ); insert( new Prince( “Mark” ) ); messenger.announceTheWedding( drools.getRule().getMetaData().get( “requirementId” ) ); messenger.announceTheWedding( drools.getRule().getMetaData().get( “requirementId” ) ); end end Use annotations Do not use metadata in conditions It is ok to use metadata in consequences If necessary, metadata is available to the enabled attribute31 Rules Fest – October 2011
    • Why Control Facts should be avoided? rule “11111” rule “11111” when when ControlFact( a[“11111”].b[this.X].enabled == true, a[“11111”].s[this.S] == true ) ControlFact( a[“11111”].b[this.X].enabled == true, a[“11111”].s[this.S] == true ) ... ... ( #rule 22222 ( #rule 22222 ... ... Breaks clarity goal Breaks one scenario – one action best practice Leads to micro-control and procedural code Usually leads to runtime overhead Sometimes, control facts are useful, but not for the general case32 Rules Fest – October 2011
    • Alternatives for control facts rule “11111 – transform the frog into a prince” rule “11111 – transform the frog into a prince” agenda-group “x” agenda-group “x” ruleflow-group “y” ruleflow-group “y” salience 10 Usually one of these attributes is enough salience 10 enabled ( ... a boolean expression ... ) enabled ( ... a boolean expression ... ) when when ... ... Use rule attributes for conflict resolution Use enabled expressions to conditionally disable rules Do not abuse of salience Let the engine do its job33 Rules Fest – October 2011
    • Why “embedded” rules are bad? ( #rule 22222 ( #rule 22222 Frog( eval( height.bigDecimalValue.compareTo( somePrince.height.bigDecimalValue ) < 0 ) ) Frog( eval( height.bigDecimalValue.compareTo( somePrince.height.bigDecimalValue ) < 0 ) ) ) || ( #rule 33333 ) || ( #rule 33333 Prince( name == “Charming”) Prince( name == “Charming”) ) || ( #rule 44444 ) || ( #rule 44444 ... ... ) ) Breaks independent lifecycle management Breaks clarity goal Breaks explanation facility goal Breaks performance goal Breaks one scenario – one action best practice Increases maintenance cost and testing complexity34 Rules Fest – October 2011
    • Alternatives for “embedded rules” rule “11111.a – Teenagers are eligible” rule “11111.a – Teenagers are eligible” rule “11111.b – Elders are eligible” rule “11111.b – Elders are eligible” when when when when $p : Person( age >= 16 && <= 18 ) $p : Person( age >= 16 && <= 18 ) $p : Person( age >= 60 ) $p : Person( age >= 60 ) then then then then insert( new Eligible( $p ) ); insert( new Eligible( $p ) ); insert( new Eligible( $p ) ); insert( new Eligible( $p ) ); end end end end rule “11111.c – Eligibles get discount” rule “11111.c – Eligibles get discount” no-loop no-loop when when $t : Ticket() $t : Ticket() $e : Eligible() $e : Eligible() then then modify($t) { setDiscount( 0.25 ) } modify($t) { setDiscount( 0.25 ) } end end35 Rules Fest – October 2011
    • Alternatives for “embedded rules” One scenario – one action Allow the engine to do its job Take advantage of flow control features36 Rules Fest – October 2011
    • Q&A Yes, we also do pair programming! Edson Tirelli etirelli@redhat.com37 Rules Fest – October 2011