Best Practices Series: Rules Writing Pitfalls
Back from vacations, I am ready to tackle a new fun project, in addition to a handful of customer projects and an upcoming product launch. I have never taken the time to write best practices on rules authoring, despite the many requests. Let’s make the time! It seems that some best practices are totally obvious to us, old timers in the decision management industry. But there is very little literature out there to help business analysts get ready to design the best business rules.
Over the course of the series, my goal is to document some guidelines that all business analysts should know to excel at rules authoring. I will start with the easiest recommendations that we have rehashed for close to 20 years now.
So what should you consider when writing rules?
Regardless of the product you use to write rules, the syntax will likely cover some basic capabilities that will get you in trouble. I considered removing these constructs from our SMARTS product when we got started. There are a few use cases that benefit from them though, so we left them… with the caveat that you should only use them if you really need them.
Do not use OR
A rule typically consists of a set of conditions, and a set of actions. These conditions are AND-ed or OR-ed. For example, you could check that:
– an applicant is a student
– and that he or she is less than 21 years-old.
Alternatively, you could check that:
– an applicant is a student
– or that he or she is less than 21 years-old.
Though these sentences make sense in English, we frown upon the second one in the industry. We highly recommend you use only AND, and no OR in your decision logic.
First of all, confusion stems from mixing and matching ANDs and ORs. It is like order of operations in math: it can give you a headache. Without parenthesis, an expression can become very confusing. For example, if you check that:
– an applicant is a student
– or that he or she is less than 21 years-old
– and that he or she is from California…
Would you expect the rule to fire for a 25 year-old student in Vermont? Furthermore, while each engine has a specific order of operations, this may not be consistent across products.
In addition to the confusion it creates, OR makes it difficult to track the business performance of each scenario. Rules provide a powerful capability to report on how many times they executed (fired), and possibly more decision analytics depending on the rules engine you use. If you bundle the State requirement with the Age requirement, you will not be able to take advantage of these analytics. This is an important aspect not to underestimate.
Why do we have OR? I think it is mostly historical. It was there when we started with Expert Systems. There are also complex rules that only look for a few alternatives for which OR could be useful.
Most of the time, this can be dealt with more elegantly by using the IN keyword. If your rule check for the state of California or the state of Vermont, then just check that the state is in California, Vermont as a list.
Do not use ELSE
Historically, rules have had the ability to include an ELSE statement. When the set of conditions is not correct, the set of actions in the ELSE statement is executed instead of the set of actions in the THEN statement.
Again, in English, that makes perfect sense. In rules, it is overwhelming. For example, if a rule checks that the applicant is at least 17 in the state of California to be eligible, the else statement will execute for an applicant of any age in any other state.
There are a few use cases in which the condition set is black & white. When it is true, something happens; when it is not true, something else happens.
In the majority of the use cases, you have more than just one rule that defines the behavior the rules look for. In that case, you are likely considering having an ‘ELSE’ statement that is global to the rule set. I have seen rule sets that needed that complex negation of all of the exceptions identified by the rules. This is not fun to write and maintain.
Alternatively, the best design here would use default actions if they exist in your system. A default action is typically defined at the rule set level and applies when none of the rules fire.
If your rules engine does not have a default action, I recommend using a 2-step process. First, execute the rules that deal with the exceptions. They will likely modify a status or log something (create an error, add a promotion, etc.). Second, in a separate rule set, deal with the situation in which none of the rules have fired by looking at the status they would have changed.
Do not use PRIORITIES
Here is another historical artifact. Priorities allow a rule to jump ahead of all the other rules, and execute first. This may be needed when you leverage the RETE agorithm, which uses inferences, and therefore rules execute continuously mostly irrelevant of order.
But in most cases, you do not need inference. The order of the rules, as they appear in the rule set, dictates the rule execution order. If you temper with priorities, the order of execution changes. This may create confusion as the next business analyst on your project might miss this little detail, and wonder for a long time why a rule that is true does not fire, or why it fires out of order.
The best thing to do if rules need to fire in a certain order is to re-order them so that they show in the order they need to be considered. If your logic is more complex, go for simplicity of design: decompose your decision into steps. One rule set might identify all the products or offers that the applicant is eligible for, while another step ranks them, prioritize them, selects the best.
Let me quote Nicolas Boileau-Despreaux, whose words inspire my rules writing!
“What is conceived well is expressed clearly,
And the words to say it will arrive with ease.”