Drools and beyond: extending our functionality

We've seen in this chapter, and throughout the whole book, a lot of different ways to use Drools. Whether we use it as an embedded library, a service, or a closed product, the main goal is to enable our applications to grow in a manageable way. We must consider our design, inside and around business rules, to achieve this. We will try to cover a few tricks that have facilitated growing our Business Rule-enabled applications in the past.

One of the first extensions of functionality we've seen for Drools components has been global variables. If we define them as interfaces or abstract classes, we can define them by using different classes for different runtime components (that is, test cases, local versus QA, or production environments, and so on). They are a very simple way of providing ease of extensibility because of their pluggable nature.

Global variables also provide a very useful feature that sometimes gets overused; because we can keep a reference to the global variables we set, and we can store information from our rule executions into it, we end up storing a lot of information in global variables that is clutter our rule consequences—for example, a log of rules is triggered:

global List rulesExecuted;

rule "example of bad action"
    when
        //our conditions
    Then
        //our actions
        rulesExecuted.add("example of bad action");
end

KieSession ksession = ...;
List rulesExecuted = new ArrayList();
ksession.setGlobal("rulesExecuted", rulesExecuted);
...
ksession.fireAllRules();
System.out.println(rulesExecuted.size());

In the previous example, we can see a common point where we start abusing global variables. Global variables, if used to record information about our rule execution, should be used to store specific business-related information. If we just want to store which rules were triggered (or a sub-group of them) or anything common to all our Drools executions, we are better off using Event Listeners. Event Listeners are the best choice when we want to audit our execution, rather than obtaining specific information about our domain. We need to keep the difference in mind when we design our runtime.

Another important aspect of rule-related application design is to make our runtime code as agnostic as possible about which specific rules are triggered. If you couple your execution to the firing of specific rules, it will be very hard to extend your application. This is also true when it comes to designing our rules. Like we said before, rules should be independent of each other, and that extends to the application that runs them; all we should care about in the execution of our rules is the final decisions made by them. Otherwise, any change or add-on in our rules will need to be impacted into our runtime as well.

This applies to creating tests for our rules. We should try to avoid validating that specific rules have fired, and rather verify that the consequences of the rule execution have been followed. For example, when testing the execution of our online shop case, we should strive to test whether the final outcome of the rules has been followed (items have been catalogued, discounts have been applied, and so on), and not just whether one specific rule or another has been tested. To put it more simply, we should let the rule engine do its job.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.21.47