Thursday, 29 November 2012
This announces the latest version of Madura Rules, part of my Madura toolkit.
Madura Rules is a rules engine that plays nicely with Java objects, the rules refer to fields in the objects and enforce validation and derive new data. This all happens transparently, and with almost no api calls. You just write your code to talk to your objects and the rules just happen.
But this was missing something I used to have in an earlier engine I built about 20 years ago: Directed Questioning.
Let's say you have a really complicated data input scenario, something like an insurance form or a tax form. These things often have a lot of questions on them that users don't have to answer because the questions don't apply. There are a lot of statements like 'go to step 17 if you answered NO' and so on. If this is paper based (and it usually is) then the amount of paper is somewhat intimidating, even when the user might only have to answer 5 questions or so. And finding which five questions out of, say, 200 is awkward.
You could build a software system that codes this kind of form, of course, and people have. But they are hard to maintain. Adding a new field or two means you have to review what circumstances a user has to supply the information and then adjust your navigation and flows to ensure the right users answer those questions.
Directed Questioning bypasses that by using the fact that the rules engine knows all the relationships between these questions and can dynamically customise the UI as the user enters the data. Here is a simple example that calculates your BMI.
formula: Customer "BMI"
bmi = weight / (height * height);
formula: Customer "Height Metric"
height = heightMetric;
formula: Customer "Height Imperial"
height = (heightFeet * 0.3048D) + (heightInches * 0.0254D);
formula: Customer "Weight metric"
weight = weightKilos;
formula: Customer "Weight pounds"
weight = weightPounds * 0.453D;
}These are the rules the engine uses. They happen to be all formula rules. We can use if/then rules as well as constraint rules if we need to, but I am keeping this example simple. The first rule is the standard BMI formula and the rest of them allow the user to enter in metric or imperial units, depending on what they prefer.
All we are really interested in is the value of bmi. We can tell the rules engine to
go figure it with a simple Java call. What actually happens then is the engine looks at the rules and sees that it needs a value for height and weight. To get weight it needs to fire either the third or fourth rule, it doesn't matter which at this point.
So it tries the third rule, and that means it needs a value for weightKilos. There aren't any rules that deliver weightKilos, if there were the engine would go look at them, so it asks for weightKilos. That's the first question the user sees.
This user is happy to answer that and inputs a value, so the engine derives a value for weight. It does not have to ask for weightPounds and it knows that. Now it is looking for height.
To get height it tries the second rule and asks for heightMetric. This user is happy with metric weights but not length and he doesn't know his height in metres. We can tell the engine we 'don't know' that value and it will look for another way to get the height.
There is the third rule which needs heightFeet and heightInches so it asks for those, figures the height and then it can work out the BMI.
So, of the 5 possible fields to enter this user was only asked for 4. If he had known his height in metres it would have been only 2.
The questions are asked one at a time, because each answer might eliminate the need to ask the next one. The API is designed to be architecture friendly, it actually queries the engine for the next field to ask for, and how it is asked (ie what technology is used to ask it) is up to the application. My current preference for these things is to use Vaadin and I have a working example on rhcloud you can look at from your browser. Log in as admin/admin and click the BMI button on the main screen.