SRE

Simple Rule Engine

version 1.3

Sierra Digital Solutions Corp

http://sourceforge.net/projects/sdsre/

 

 

 

If you find this application useful we would like to hear from you, feedback is what drives the project.

 

 

 

 

 

What is a rule engine?
A Rule Engine is a software system that contains rules on behalf of another system. Many different kinds of rules can be contained in a rules engine: business, legal, company policy, navigation, computational. An example, a website that prompts the user to fill out a form that has dependencies between pages could use a rule engine to control the verification of the validity of the form and the navigition between pages. Another example, a bank could have a set of rules that dictate the interest rate and fee's associated with a checking account. It also provides a means to classify and manage rules in a centralized location instead of being hardcoded throughout an application.

 

Why use a rule engine?
Most companies business strategies are constantly in flux due to their changing internal and external environments; the CEO has a new idea on increasing sales, consumer base is being eroded by a more aggressive competition, current business practices wiill soon be out of compliance due to changes in regulations. How do handle changes in a system in an maintainable, reusable, extensibility, and ownership?

Maintainability is increased by using a rule engine by centralizing the rules. Typically a non-rule engine based systems that contain rules of moderate complexity will implement its rules in methods of objects that encapsulate business logic (business objects). They refer to other business objects that form associations with other business objects, typically creating an intricate web of associations. Since these objects are tightly coupled changes to them can have rippling effects throughout the collection. Clarity of the rules in such a system can be quite poor when the rules cross these objects. Not only is it difficult for a developer to understand the details of such relationships, but even more so to change them.

A rule engine based system will contain rules of another application thus seperating its rules from its controller. Typically a rule engine based system will use a proxy class that delegates a call to a rule engine. Rules implemented in a rule engine are declaritive in nature. That is they are essentially a set of if...then statements, and as long as their condition(s) do not contain a dependency to other rule they are completely decoupled from eachother. Whether they fire or not has nothing to do with other rules, in fact it is as if there are no other rules. It is now possible to group rules, thus bringing clarity.

Extensibility of requirements is increased in a rule engine due to its declaritive nature. In a non-rule engine based system, adding new requirements would possibly mean new associations and as mentioned new associations across business objects could have a rippling effect. A rule engine based system will not have this problem since the rules have a higher clarity and are loosly coupled. New sets of rules can be added to the system with no effect on the existing rules.

Reusability of requirements is also increased in a rule engine due to its declaritive nature. Often its a requirement that a system can operate based on multple requirements. For example, a business wants its pricing policy for new customers to change at midnight in two weeks, while existing customers remain at their current pricing policy for the remainder of their term. Using a business object model would require multiple business objects heirarchy, that is one heirarchy for new customers and another for old customers. Or multiple business objects of the same type to distinguish between new and old customers. Or switch statements inside business object(s) methods. A rule engine based system would simply contain in the condition the term start date and decide for itself which ruleset(s) to execute.

Ownership of rules can be shifted to business units with a rule engine, especially with SRE. Rules being declarity in nature are easy to understand. The learning curve that business users would have to overcome is relatively small: XML and testing. SRE was designed around its rules being contained in a simple to understand XML file, hence the word SIMPLE in SRE. XML should take no more than a day to learn; they even have XML for dummies and XML in 24hours books. Implementing rules should have no to low learning curve, anyone who can form if..then statement, thats just about all of us, can write and maintain rules. This is actually a huge gain for business groups, they now have a way to easily own their own rules, no longer do they need to try to explain and hope developers understand what they want.

On the downside, not every system should use a rule engine. Rule engines do increase the risk and complexity to the project, and proper knowledge of how to successfully implelement a rule engine should not be taken lightly. It is critical that a system be designed with the proper data interface to the rule engine. Not doing so will severly limit its usefullness.

In conclusion, entropy (randomness) of requirements are lowered with a rule engine, they can be centralized and grouped together in a manner that adds clarity in a XML file that simple yet powerfull enough to allow even business owners to own the rules.

 

What is SRE (Simple Rule Engine)?
From a technical perspective, SRE is a comprehensive, flexible product aimed at enabling software developers to create applications that can be mainteained with minimal effort and directly supported by designated business users. It leverates the flexibility and robustness of XML into a context that business users can understand and own freeing developers to work on new functionality.  It allows developers to combine rule-based and object oriented programmng methods to add business rules to new and existing applications.  Hence the name of this product, Simple Rule Engine.

 

How does SRE simplify our development?
1. SRE makes it easy to create, edit, store, and organize rules.
2. SRE's XML is the simpliest possible manner of describing rules.
3. Rules are declaritive, not procedural, in nature allowing problems to be broken down into discrete pieces.
4. SRE allows rules to be seperated from your application allowing for flexibility for future changes.

 

Why would I want to use SRE instead of a full blown rule engine?
A full blown rule engine, like NxBRE (also open source), is far more capable than SRE but it comes at a price. That ability has a price, SRE has far better performance and is far easier to understand. Not every application needs the complexity of a bull blown rule engine, sometimes a simple one will do just fine and sometimes it wont. Choose wisely.

 

What kind of rule engines are there?
Chaining refers to the relationship between the rules; forward and backwards refer to the direction of that relationship.

Forward chaining : Often refered to being 'data driven' due to the fact that the data determines the truthality of the rule.
(Rule) If my car is green, then
(Action) my house red.
(Fact) I have a green car.
(therefore) I have a red house.

Backwards-chaining : Often refered to being 'goal driven' due to the fact that we are trying to determine if something exists based on existing information. 
(Rule) If my car is green, then
(Action) my house red.
(Fact) My house is NOT red.
(therefore) I dont have a green car.

hybrid :  combination of the above two.

 

What is contained in a rule engine?
Rule engines typically support rules, facts, priority (score), mutual exclusion, preconditions, and other functions. Because SRE's goal is to be simple and not a full blown rule engine, it only supports rules, facts, and actions.

 

What kind of rule engine is SRE?
forward chaining

 

What is declararitive programming?
(modified version from drool)
Declarative programming deals with what is, as opposed with the how to normally encountered in imperative programming languages. SRE allows for rules to be decoupled and lowers the unidirectional logical flow. Declarative rules typically take the form as follows:

if ( condition)
then ( action)

Declarative statements state  what should occur, but do not specify the procedure for actually testing the conditions. For example, an imperative method for ensuring you have an umbrella if it is raining would be:

  1. Step outside and determine if it is raining.
  2. If it is raining, then go to the closet and get an umbrella.

The above could also be represented by two declarative rules:

If it is raining
Then you need an umbrella

If you need an umbrella
Then get one from the closet

Given declarative rules, the knowledge that it is raining could produce two
courses of action:

  1. You already have an umbrella, perhaps because you always carry one, in
    which case, you're ready.
  2. You don't have an umbrella, so you go get one from the closet.

This allows you to come by the knowledge that its raining in more than one way, and respond to that knowledge in the most appropriate fashion, depending on other available knowledge. For instance, if you know you're going to be away from the house and that it is likely to rain, you can add another rule to the ones you specified above:

If it might rain later, and
If you'll be away from the house
Then you need an umbrella

At this point, you only need to go get an umbrella if you know you don't already have an umbrella, and either that it is raining, or that it might rain later while you're away from the house. If you were to write that all out in procedural code, it'd quickly get tangled and complex. Imperative logic helps us decompose complex decisions into mind-sized pieces.

 

What are Facts?
"Something demonstrated to exist or known to have existed" as defined by dictionary.com. Its a fact that today the sky is blue, its a fact that my car is red. Facts are immutable once their value has been determined. Facts can have essentially any value.

 

What are Rules?
Rules are Facts with conditions and possibly actions. If your house is blue then your car is green. If your in an accident then your insurance premium will increase. Rules actually inherit from Facts; they too are immutable once their value has been determined. Rules are only true or false. What are Actions? Actions are causation of changes from facts. In the last rules example, your insurance company will increase your rates if your in an accident. Actions currently can assign a value from another fact or set a fixed value, callbacks are a future enhancement.

How do Facts, Rules, and Actions work together?
Facts contain the data from our model (incomming data). Rules also have a value the instant their dependent facts are given a value. Actions are performed the instant their Rules evaluate to true. While obviously to our computers these determinations have to be calculated, but from the view of our client program they are instant; the client must wait for a response.

 

What does SRE's ruleset look like?
(see unit test cases or examples)
<RuleEngine>
<Rules>
<Rule id="R1" desc="expression">
<Condition><![CDATA[ ISNULL(FACT(In)) ]]></Condition>
<Actions>
<Action factId="Out">
<Expression><![CDATA[ 5 ]]></Expression>
</Action>
<Action factId="Out" result="false">
<Expression><![CDATA[ "" ]]></Expression>
</Action>
</Actions>
</Rule>
</Rules>
<Facts>
<Fact id="True" desc="True" type="boolean"> <xpath><![CDATA[ boolean(1) ]]></xpath> </Fact>
<Fact id="False" desc="False" type="boolean"> <xpath><![CDATA[ boolean(0) ]]></xpath> </Fact>
<Fact id="String" desc="True" type="string"> <xpath><![CDATA[ 'string' ]]></xpath> </Fact>
<Fact id="In" type="double"> <xpath><![CDATA[ //number1 ]]></xpath> </Fact>
<Fact id="Out" type="double"> <xpath><![CDATA[ //number2 ]]></xpath> </Fact>
</Facts>
</RuleEngine>

 

What are the elements in our XML Rules?
RuleEngine : the root node, it contains all the rules and facts.

Rule : declares a rule
Condition : declares the expression necessary to evaluate to true for actions to fire. this expression MUST always return true or false or an exception will occur.
Action : specify the fact that they are to be applied to and the expression, expressions being returned can be of any type.

Facts : declare a fact, facts are statements about data and get their data from the model.
type: specify the type of the value. 'boolean', 'string', 'double' are supported types.
xpath: specifies the xpath necessary to return and set the data. If its unable to set data an exception will be thrown.Currently only the first nodesets value will be taken, or the evaluated value for non-nodesets.

 

How are rules executes?
Once the rules have been set to a model (XmlDocument), the rules are automatically fired as the xmldocument object is modified. For example...

model["a"]["number1"].InnerText= "15"; //rules are executed because of this

could fire multiple rules due to this change. Its important to note that rules are ONLY fired if there is a change in value. That is if the above line was execute 20 times in a row with the same value the rules involved would still only be executed once! To have multiple firings, clear the value and then set it again. See bank account example.

 

How about a full example on how to execute rules?
public void xxx()
{
ROM rom = new ROM(); //rules
XmlDocument rules = new XmlDocument();
string directory = AppDomain.CurrentDomain.BaseDirectory + @"\..\..\Tests60-69\TesterR60.xml";
rules.Load( directory );
RuleEngine.Complier.XmlComplier.Compile(rules, rom); //model

Debug.WriteLine( "\n\nAttaching model.......");
XmlDocument model = new XmlDocument();
model.LoadXml("<A><NUMBER1></NUMBER1><NUMBER2></NUMBER2><RESULT></RESULT></A>");
rom.Model = model;
Debug.WriteLine( "Model attached.......\n\n"); //attach no model

Debug.WriteLine( "\n\nModifying model.......");
model["a"]["number1"].InnerText= "15"; //rules are executed because of this
Debug.WriteLine( "Model modified.......\n\n"); //now our other xml values should be set
Debug.WriteLine(model.OuterXml);
Assert.AreEqual("3", model["a"]["number2"].InnerText);
}

 

What operators can be used in expressions?
It is important to note that all operators, expressions, and facts id's are case sensitive.
ISNULL
FACT
==
!=
-
+
*
/
AND
OR
NOT

 

How can I know how my rules are being executed?
First set the references to the debug dll's. These dll's have a huge performance hit in performance BUT also dump their workings to the console or other registered listeners. Then run the program.