[A list of considerations for DROOLS.  Salience is a mechanism in DROOLS for controlling the sequence of rule evaluation.  Other BRMS have similar considerations – ILOG: priority, XpertRule: dynamic.]

⁞⁞⁞⁞ Remove all Salience and make rules independent

Salience is the equivalent of a goto command, meaning that, to understand the sequence of processing of rules in a DRL, the developer has to search from top to bottom, mentally creating an ordered list.

Salience allows rules to share the same level, meaning that the order of rule firing is not fully specified.

The possible use of dynamic salience adds a further complication.

In addition to inhibiting the developer’s ability to understand the rule, it does mean that a rule within the DRL cannot be re-used elsewhere.

Also, if the same rule is required twice in a DRL at different levels of salience, the rule has to be repeated in full.

Salience does interact with no-loop, in a multi-rule DRL.  Generally at the end of each rule, the facts need to be updated with an update(), insert(), retract(), or modify() command.  These commands will re-trigger other rules in the same DRL that use the same class, irrespective of salience or no-loop.

Rules specified at the same salience execute in a specific, logical, repeatable, but partly data driven order.  This means that a small test will run the same every time, but once complex data arrives, the order may change, depending on previous activity.

The effect of this is to make thorough testing and debugging almost impossible: odd errors will occur in production and will not be repeatable in other environments.

Obviously the solution is to remove salience and implement the sequence of rules in ruleflows.

For very large systems this may be impractical.  Simply making sure that rules do not have the same salience will go some distance to correcting this.

Note that rules with no salience have implied salience zero.



⁞⁞⁞⁞ Keep all logic in the rules (as far as possible)

Experienced developers may be reluctant to learn new tools, and fall back on java to solve problems.

In DROOLS these are manifest in the LHS in eval() statements, or in the init() section of accumulate statements.   On the RHS external logic can be invoked anywhere.

If these objects interact with external systems in any way, the results can be unpredictable, and seriously impact performance.  For example, there can be considerable high-speed traffic of tuples internally within DROOLS that can easily swamp a database.

Equally, external logic will defeat one of the primary purposes of DROOL: to make the rules accessible.

So, unless there is good reason, all logic should reside in the rules.


⁞⁞⁞⁞ No Activation Group or Global

Activation Group suffers from many of the same issues as salience: please read the above notes.

Global is a special type of object intended for a very specific use.  Unfortunately its name suggests it is a freely declared variable accessible in the LHS, which it is not.

Any attempt to use global will likely result in long hours of debugging, and, finally, a regression to the standard method of inserting classes as facts.


⁞⁞⁞⁞ No Update (maybe)

[This is included for completeness, as an example of current practice, but, depending on the use-case, not necessarily best practice.]

The commands that change the facts are: update(), insert(), retract(), or modify().

The effect of these can be unsettling to a developer in that they trigger a re-evaluation of all the rules in the current DRL that use that fact class.

(This problem is not unique to DROOLS: XpertRule and GURU both have mechanisms for handling the re-evaluation of “dynamic” as well, and cause equal confusion amongst developers).

If there is a single rule in the DRL, the problem is completely corrected by the no-loop statement.

The scope of no-loop is only one rule, so if there is more than one rule in the DRL, then two rules changing the same fact class can interact with each other, creating infinite loops.

Some architects have banned the use of the change commands [update(), insert(), retract(), or modify()] in favor of a “dirty update”: an example is to be found in Wolfgang Laun’s paper, for exactly the same reason: to circumvent the interaction with other rules.

A dirty update means updating the facts external to DROOLS via code, usually in the RHS, but also sometimes in the LHS.

Separating the rules into a ruleflow, with one rule per DRL, and using no-loop does  largely eliminate this problem too.

It can also be overcome by having two classes for each fact that poses this type of problem, keeping the update in the RHS separate from the LHS.