A re-occuring theme that I see a lot in ODM implementations at Modexe are heavy, highly nested and business logic rich rule flows. These flows typically try and control the rule execution down to a very granular level, and this often results in a loss of business agility for the business rule authors.
Daniel Selman has written an excellent article on different approaches to iterating over collections in ODM, one of which is using rule flows (see: https://www.ibm.com/developerworks/community/blogs/brms/entry/iterating_over_input_input_parameters_ruleflow?lang=en).
I quote from his article: “It smells like the programmer is…trying to impose procedural control over the execution of the rules”. This is a very true statement, and whilst it tackles a slightly different issue, it very much applies to the problem set out in this article. Often the power and flexibility that ODM gives to the users to affect business decisions and outcomes, is then nullified by highly procedural and traditional programming approaches.
Why is this a problem?
This becomes a problem because the Decision Centre users (e.g. non-IT, business rule authors) have no way of maintaining the rule flow. So if the business needs to change the flow of the rules, or change the conditional logic in the rule flow to execute different rule packages, then it becomes an IT change. This is particularly an issue if the logic is based on business data whose values may expand and grow over time.
Rule flows in themselves are easy to change within Rule Studio, but as soon as you go into an IT change cycle, then you may have to wait weeks for a change, and often the change will be prioritised behind more urgent changes.
It should also be noted that rule flows are interpreted at execution time in the engine, so the more branches and nested flows there are, the poorer the performance will potentially be.
An example of a rigid and inflexible rule flow
Imagine that an organisation services multiple customers and offers customised pricing for each of those customers. They may have base price rules which set the base prices for various products, which are then adjusted and overlaid with customer specific pricing.
The rule project structure and rule flow in this example might look like the following.
Figure 1: Organisation of the customer rule packages
Figure 2: Rule flow with customer specific logic
The first two rule packages contain setup and base pricing rules, and the final rule package contains rules that perform any final calculations.
In the middle of the flow you can see that there are three conditional branches, each of them corresponding to a customer, where the rule packages contain customer specific pricing rules.
From a rule organisation/cataloguing point of view, putting the rules into these packages is a good idea, as it helps the users with rule maintenance and navigation in Decision Centre. But of course, if the business takes on a new customer (or indeed stops servicing a customer), then this will require a change to the rule flow.
What is the alternative?
The alternative is to keep the customer rule packages as before, but put them all into a higher level package that can then be referenced in the rule flow. For example, the two figures below show how the package structure could be organised in the rule project, and how this would then be reflected in the rule flow.
Figure 3: Organisation of the customer rule packages
Figure 4: Referencing the high level “Customer Rule” package
As you can see, the rule flow is now data agnostic, with any rules inside the “Customer Rules” package, as well the rules inside any further sub-packages (e.g. customer specific packages), being executed (if applicable) with no changes to the rule flow. If the rule author in Decision Centre adds new rules to this package, then these will be automatically added to the selected rules for execution (again, if applicable).
But how will the engine know to only run rules for specific customers? Well, there are a couple of options depending on the rule type. For Action Rules and Decision Tables, you would specify the customer name or Id as a condition in the rule, or if using a Decision Table, you could put the customer name or Id in the pre-condition of the rule instead so it only has to be set once.
How should a rule flow be used?
Rule flows should be used for very high level orchestration of packages of rules, or branching on high level decision outcomes. They also allow for the segmentation of logical rule groups, so that only those groups that need to be executed are done so, thus giving a performance benefit for rule sets that might have a large number of rules.
Take the classic example of eligibility and pricing rules, which demonstrates both points. The eligibility rules will check the suitability of the customer, if they pass the checks, then the products are priced for the customer. If the customer is not suitable, then no pricing is performed and a decline indicator is returned back to the calling application.
An example rule flow might look like the following (taken from the ODM 8.5 samples).
Figure 5: Pricing and eligibility rule flow
As you can see, there is no reference to specific data values in the rule flow, only a check performed on a high level decision outcome, i.e. is the customer eligible or not. It is very unlikely that this flow will ever change, after all, the business policy is to only offer a price if the customer is suitable. But the rules that drive the conditions for eligibility are fully encapsulated within the “eligibility” package and are under the full control of the rule authors.
It also shows how the rules are grouped according to their business function, so that only the pricing rules are ever executed if the customer passes the eligibility check.
The overall conclusion is that when designing a rule flow, try to avoid using business data directly in the rule flow conditional branches.
What you should be aiming for is branching on high level business outcomes, driven by the rules themselves, at a level that reflects the overall business policy.