There was a lot of use of the “F” word at last week’s CodeMash conference. You know the word: “Functional”, as in Functional Programming.
My past self-driven learning includes playing with Prolog and a casual tracking of progress by the Artificial Intelligence community. One actual assignment required XSLT transformations; Prolog had prepared my brain for the <xsl:apply-templates> pattern-matching and recursion based looping concepts.
I attended several of the Functional talks with a few driving interests: simplifying parallel and concurrent programming, and implementing flexible rules engines. I also wanted to validate our team’s use of lambda expressions and delegate functions in C#.
However my main interest right now involves rules engines. In particular, those that can be invoked from a larger application centered on Java.
In my day job I sometimes have a need for a business rules engine. In simple cases, we hammer out imperative code with gauntlets of if/else or switch/case statements.
Our current application uses the Declarative Programming aspect of Structured Query Language (SQL) to implement a set of dispatching rules. An Oracle database holds the set of source entities as well as the potential target entities. The rules engine acts as a matchmaker between sources and targets, driven by a hierarchy of inclusion and exclusion rules. These rules are also stored in the database. The precedence hierarchy between the rules is hard-coded in the SQL query that applies the rules to the business entities.
This SQL based approach works because the Relational Algebra behind relational databases is ultimately based on the rules of grammar. A well modeled database has Entities acting as nouns, Relationships acting as verbs, and Attributes acting as adjectives and adverbs. A row in a table in a well modeled database can be read as a statement of fact: “Customer ABC made a Purchase of 10 units of Model XYZ Widgets on July 14 for a Unit Price of $12.”
The biggest problem with this approach is the monolithic SQL query that combines the rules data with the business data and applies the precedence hierarchy. Existence checks use the typical Left Join … Where … Is Null pattern. Precedence is managed by parenthesized nesting of And and Or expressions in the Where clause. The main Select list contains Case When … expressions that compute Boolean decision values to simplify the Where clause.
It all works, but it is barely maintainable. It is testable, however; a preplanned set of facts and rule settings are loaded into a QA database instance, and the big SQL query is run. The result set is then checked for existence of expected matches and exclusion of unexpected matches. Changing the precedence hierarchy of the rules, or adding a new class of rule, requires reprogramming the big SQL query. In turn this requires a round of regression testing and a formal deployment of any subsystem that invokes the rules after a database update.
Going forward a better way is needed.
Prolog has always been in the back of my mind. The issue has always been how to integrate it with a real world business application.
The talks at CodeMash give me new hope that an appropriate Functional Programming language can be integrated with the Java environment we are migrating to. It appears we can go off road from Java just enough to implement the rules engine and keep most of our logic in Java itself. After all, we need to allow future staff of varying experience levels to support all this.
Look for more posts as I analyze what appear as the most promising options based on my post-CodeMash research and experimentation.