Simple Rules Engine

Here is a rules engine that is internal to the .Net Framework.

This is the kind of rule that I can use:

<RuleSet.Text Name=’Text Ruleset’ Description=’Test Ruleset’ ChainingBehavior=’None’>
<Rule Active=’True’ Name=’R1′ Description=’Checks Name’ Priority=’1′ ReevaluationBehavior=’Never’ >
<Condition>this.Name == null</Condition>
<Action>this.ValidationMessages.Add(“Name should not be empty”)</Action>

The following is a unit test that executes the above:

public void FileStringRule()
TextRuleSetSerializer rs = new TextRuleSetSerializer();
RuleSet Rules = rs.Deserialize(typeof(Person), File.ReadAllText(@”.Ruleset.Rule”) );
Person p = new Person();
RuleExecution execution = new RuleExecution(new RuleValidation(p.GetType(), null), p);

Assert.AreEqual(1, p.ValidationMessages.Count);

Here is the definition of Person:

public class Person
public string Name { get; set;}
public int Age { get; set; }
private List<string> _ValidationMessages = new List<string>();
public List<string> ValidationMessages { get { return _ValidationMessages; } }

The beauty of this is that we have externalised the business rules in an efficient, readable compact form that makes no assumptions about the specific types.  The RuleEngine is passed a POCO to act as a Fact.  The Fact object is used to provide the details to the rules and collect the results.

By keeping the business rules externally to the application allows suitable changes to the logic to be made without requiring recompilation.  It is even possible to update the rules used by an application without requiring a redeploy!

However should you be prepared to take a dependency on a specific base class can I suggest that you look at the PerfectStorm.Model. This provides a base class that forms an Aggregate with a fully defined type system. It has the unusual property of being designed to permit invalid input to be entered. This allows an integer field to be set to the string XXX. This allows a single rules interface to perform complete declarative error handling – we don’t use one set of rules for parsing and another for buisiness logic. We can use rules to state what is an isn’t valid by providing an external ruleset. PerefectStorm.Model is intended to be a pure model class. It knows nothing of databases or user interfaces. It can hold data that an external class can use to map to these, but that is not it’s responsibility.

You need to be careful as to the specific goals of the rules engine. They are typically used to answer questions (Is this data valid? Could I save this to my database?) or to provide sensible defaults or to perform calculations (localised tax code calculations). These are also eminently suitable for unit testing and code generation.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s