Skip to main content

Ruling Out: Rule Engines and Declarative Programming Come to Java

August 19, 2004

{cs.r.title}










Contents
Why Rule Engines?
Standards and Specifications
Developing with Rule Engines
A Declarative Programming
Example
Advantages

Hello, and welcome to the first installment of Ruling Out, a new column on rule engine technology and declarative programming in Java. Every month (or thereabouts), I'll explore two new aspects of rule engine technology for the Java platform. I'll compare open source Java rule engines, supply you with tips on declarative programming strategies and tactics, walk you through examples on how to integrate the new standard Java rule engine API (JSR-94) with your existing applications and frameworks, discuss emerging business rule language standards and even show you how to write your own. I'll show you how to use rules to write intelligent agents, drive workflow systems, incorporate rules into your existing enterprise applications, and all manner of other fun topics. I'm looking forward to it, and I hope you find the column informative and enjoyable.

Why Rule Engines?

If you're like I am, you're probably cautious about "new, cool" technologies. You're probably wondering what all the hype is about rules and rule engines. In particular, what is so interesting about rule engine technologies that they deserve their own monthly column? What practical gain can be found in researching rule engines? Is this just another round in the hype cycle, where writers like me talk up the newest "geegaw" technology and try to pawn it to the masses? There are many reasons why I do not believe that to be the case, and why rule engines deserve a lot more press than they've been getting.

Until a few years ago, rule engines were largely regarded as the tools of academics and massively large-scale enterprises. That is changing. In recent years, rule engines have won more recognition for their impact on business process automation, government, law enforcement, industrial automation, transportation, and finance. Their traditional role in artificial intelligence systems has made them useful in the burgeoning video game industry. Rules can simplify knowledge transfer between different parties in business relationships, make complex decisions, and direct behaviors.

You might be surprised to discover that rule engines receive a lot of attention in the insurance claims, tax preparation, and medical industries. Sometimes, just having a system that can sift through reams of data and highlight the extreme cases can be of tremendous help.

Businesses like rule engine technology because it gives them the ability to create intelligent agents, extremely customizable user experiences, fine-grained business relationships for online commerce, and robust customer-relationship-management packages. On one end of the market, Microsoft includes a rule engine in their BizTalk application server. On the other end, the Open For Business Project incorporates a rule engine of its own.

Rule engines can also be used to build expert systems, which may be thought of as large rule banks that are tuned to a specific problem domain, such as workflow automation, resource exploration, or medical diagnosis.

In addition to all of the industrial uses for rule systems, a handful of communities have begun springing up around rule engine technologies. Javarules.org and Business Rules Community are the most notable among them. Once you get a sense of the "big picture," you begin to see rule engines everywhere you look. In that sense, this isn't a "new, cool" technology so much as a well-established technology with broad industry demand and improving support.

Standards and Specifications

That demand and support have spawned an effort to create a standardized rule engine API for the Java platform. In November 2003, the Java Community Process released the final version of the JSR-94 specification. JSR-94 formalizes a basic API for working with rule engines in Java. Since then, a handful of open source rule engines have begun building JSR-94 compatibility into their projects, and one or two are working toward full compliance (most notably Drools, which recently passed the JSR-94 test compatibility kit).

The JSR-94 specification is by no means complete, but it gives client code a unified front end for plugging into different rule engines at runtime. It also supplies a standard way for rule authors and administrators to build and deploy groups of rules in a runtime environment.

Great strides have been made in the last year to bring standards-compliant, open source rule engines to the market. As a result, enterprise developers have a powerful new tool at their disposal -- one that, as I will try to illustrate, has the potential to improve the way we program; save us valuable time, effort, and aspirin; and challenge the way we approach application development.

Developing with Rule Engines

But I still haven't answered the question, "Why?" Why are rule engines so attractive? It's fairly easy to see why rule-based approaches attract the support of business executives. But from a developer's standpoint, what do they bring you?

Ultimately, rule engines are used when you need to work with large sets of rapidly changing data in ways that would be too complex or cost-prohibitive to do manually. You could say that about all computers, but there's a hitch involved. It's a question of complexity and rapid development. Rule engines are usually designed to allow a constant and flexible addition of rules and data, to centralize rules and make them easy to manage, and to reduce the difficulty of modeling extremely complex knowledge systems in a way that other computer programs often can't.

Which begs the question -- how do rule engines do this? How do they reduce the complexity of large fact-manipulation systems and complex behavioral patterns? The real advantage that rule engines bring you, the developer -- and now we're getting to the fun part of the column -- is the ability to bring declarative programming techniques to bear on your software development efforts.

Declarative programming is distinct from imperative programming, which is more commonly known as procedural programming. Like object- and aspect-oriented programming, declarative programming is a full-fledged style of software engineering, well suited to a specific branch of software engineering. Declarative programming has been around for at least 30 years, but is presently enjoying a renaissance due to the rise of open source software, XML, and a reinvigorated interest in rule engine technology.

A Declarative Programming Example

Declarative programming concerns itself with "what is" instead of "how to." It concerns itself with the examination, manipulation, and generation of knowledge and facts, instead of process and methods. Here are some pseudo-code examples of declarative programming:

If you want to eat out,

If your favorite restaurant is open,

Then you should go to your favorite restaurant.


If you are hungry,

Then you need to eat.


If your stomach is making noises,

And if you've not eaten in several hours,

Then you are hungry.


If you need to eat,

Then you want to eat out.


If you need to eat,

And if it's later than 9PM

Then you want to eat in.


If you need to eat,

And if it's between 12AM and 2AM,

And if you live in Minneapolis

Then call Burrito Loco for home delivery.


If you buy a burrito,

Then you get chips for free.


If you buy twenty dollars worth of groceries,

Then you get a ten percent discount.


If you're a member of the diner's club,

Then you get one meal a month for free.


Unlike in imperative programming, the order that these rules are listed is not important. They all apply, all the time. A change in the "facts" in the system can cause hundreds of rules to fire off, potentially altering other facts and creating a virtual brain-storm inside of the rule engine. More sophisticated rule engines and semantic models can express more sophisticated concepts, but they all focus on the manipulation and examination of "facts" in a system.

By contrast, in procedural programming, your code is concerned with the question of how to -- your focus is given to control flow, recursion, iteration, maintaining the state of data, and the process by which certain goals and tasks are accomplished. Of course, evaluation of information plays a role in this process, but the inherent complexity of scaling a procedural program affects the upper "resolution" of knowledge that you can work with in the overall system. Let's take the example above and show how some of this might look in Java:

if(person.stomachInKnot &&
   person.getHoursSinceEaten() > 5) {
  // hungry.
  if(time.between("12AM", "2AM") {
    if(person.inCity("Minneapolis") {
      call("burrito");
    }
  } else if(time.before("9PM") {
    // ...
  }
  // ...
}

I'm not going to continue, because I've already run into a major problem. I've got to write Java classes to encapsulate all of these trivial knowledge structures. In a rule engine, I can simply assert a string that says "I live in Minneapolis" into the working memory, and it becomes a fact that I can check for in other rules. I don't have to model the subtle nuances of the decision-making logic. If you want to add trivial details to the decision-making process, you don't need to build an enormous object infrastructure around it, especially if it only applies in rare or odd conditions.

Rule engines let you focus on evaluating facts and using them to infer more facts. While languages like Java can do this with simple if/then statements, there's always a temptation to work control flow and procedural programming techniques into your code, and there's the onus of capturing everything in object code. That practice, for reasons I've only begun to allude to, does not always scale.

The thing you'll immediately notice about the declarative approach to programming, is that it follows the "if, then" pattern over and over again. This is the telltale signature of declarative programming. While in Java the if {} else {} structures form a hierarchical tree, rule engines assemble something more like a complex net, with dozens, even millions, of interconnected nodes.

Rules examine facts and figures, and either use that information to generate more facts and figures, or direct another system to perform some tasks. You could think of the rule engine, then, as the "brains" of an application, while the procedural parts of the application make up the brawn.

Advantages

This "directed action" approach allows for a greater degree of procedural flexibility than the "self-directed" imperative approach I showed you earlier. In the self-directed approach, the order and number of steps and decisions is hard coded into the program. If you were to start factoring all of the minute facts and decisions you used in the second example, you'd quickly see that the procedural technique becomes unreasonably complex, especially when the rules can change on a frequent basis.

Another advantage to this approach is that you can enter it at any state. For instance, if you already know that you're hungry, you don't need to consider why your stomach is in knots. You're hungry. You know this. The rule system doesn't care (or even know) that it's involved in a process. It is just reacting to a series of changing facts.

This flexibility allows you to continuously adapt the system to changing needs. Perhaps the burrito joint is moving locations and you need to change your late-night eating strategy in the short term. This ability to spontaneously (and appropriately) react to changing conditions is nearly impossible to capture in a software system before the fact, which means you need a way for humans to direct change in the behavior of the system. Having the executive logic of that system organized in a centrally manageable location is crucial. In more ways than one, rule engines introduce a genuinely human element to software systems.

Rule engines and declarative programming give you the ability to quickly alter the behavior of your system in a way which is difficult to program in raw Java, and to manage and interact with data in a more human way. You can still let computers do the heavy lifting, but you reassert the role of the human in the driver's seat. By explicitly abstracting the control over the behavior of the software (workflow) from the procedural aspects of the software (action), you can build much more powerful systems.

In the coming months, we're going to explore many practical examples of how this is done, and wade through some of the "cool, new" technologies as well. As I mentioned before, we've quite a bit of ground to cover. See you next time!

N. Alex Rupp studies theoretical geometry and classical literature and is conducting ongoing research in declarative programming.
Related Topics >> Programming   |