A Rules Engine in 11 Lines of JS

Dre May
4 min readAug 10, 2022

--

The concept of a rules engine will inevitably come up at some point if you are a developer. The flurry of phrases from business people and developers alike will range from “You can’t write that many IF statements” all the way to “We need to foster citizen developers to get this out of IT”.

This will lead to a search for [insert language here] rules engines, on Github or just a general Google search. Scouring through the ads of commercial companies, the allure of a rule engine becomes mysterious and mystical in nature. Of course Drools / JBOSS Rules will show up in that list, and you will have to figure out how to Dockerize it and stitch it into your environment.

Peeling back the onion

So what if we try to peel back the onion? Is a Rules Engine just a more elegant way of organizing a bunch of IF statements? It seems potentially similar to the Chain of Responsibility design pattern, but does it completely fit here? I decided to take a look, using some pseudo code. But when I was done, I took a second look, and it appears I had built an actual functional rules engine. In only 12 lines of JavaScript!

The General Concept

The general concept of a rules engine, is that you have a set of “facts”, and then actions or outcomes that result from a set of rules. The classic example for a rules engine, is something like:

Rule: If it is raining, take an umbrella.

Fact: It is raining.

Outcome: Take an umbrella.

Initial Example

Instead of trying to write the “engine” first, I took a crack at writing how this could be passed into a general purpose evaluator.

I came up with something like this:

The example topic was generally taken from the Wikipedia article on Decision tables: https://en.wikipedia.org/wiki/Decision_table

Using ES6 arrow functions, and having one parameter that contains the “facts”, how concise could things get? It’s not as concise as putting the facts in an Excel spreadsheet type table, but the goal was to understand the concepts, and not re-build an elaborate engine. In this form, the rules almost appear if they have been written in a dedicated DSL (Domain Specific Language). So, the only thing left was to add an implementation! So let’s see how the 12 lines of JavaScript stack up.

The 11 Lines

The above class has two specific facets:

  1. Collecting the set of rules.
  2. Providing an iterator that executes the rules based on a set of “facts” or “domain”, and returning when a rule is true.

There aren’t any fancy features here, but again, the goal is to understand the mechanics behind a rules engine, and not to build something on parity with Drools.

The interesting tidbit is the execution of a rule by simply assuming its a function that has been passed in with:

rule(domain)

This executes the code that has been passed in, and assumes completion if a true result is returned.

Adding a few more lines after our rules evaluation, will yield the below console output:

Output:

The full example

Below is the full example that you can copy in paste into your own environment:

class RuleEval {
ruleSet = new Map();
addRule(rule, result) {
this.ruleSet.set(rule, result);
}
evalRules(domain) {
for ( const [rule, result ] of this.ruleSet ) {
if ( rule(domain) ) return { rule: rule, result: result };
}
}
}
let ruleEval = new RuleEval();
ruleEval.addRule(
(facts) =>
facts.temp > 100 ,
'dont play golf!'
);
ruleEval.addRule(
(facts) =>
facts.outlook === 'sunny' &&
facts.temp > 95,
'dont play golf!'
);
ruleEval.addRule(
(facts) =>
facts.outlook === 'overcast' &&
facts.temp > 50 && facts.temp < 70 &&
! facts.windy ,
'play golf!' );
let answer = ruleEval.evalRules(
{
outlook: 'overcast',
temp: 65,
windy: false
}
);
if ( answer ) {
console.log ( `Rule: ${answer.rule} result: ${answer.result}` );
}

Conclusion

Hopefully this example provides a useful start on exploring how the concept of a rules engine works. In its crudest form, it could potentially make a tree of IF statements look more elegant than they really are.

--

--

Dre May
Dre May

Written by Dre May

I love writing about all technology including JavaScript, Java, Swift, and Kotlin.

Responses (1)