Question

For a large enterprise app, everyone knows that being able to adjust to change is one of the most important aspects of design. I use a rule-based approach a lot of the time to deal with changing business logic, with each rule being stored in a DB. This allows for easy changes to be made without diving into nasty details. Now since C# cannot Eval("foo(bar);") this is accomplished by using formatted strings stored in rows that are then processed in JavaScript at runtime. This works fine, however, it is less than elegant, and would not be the most enjoyable for anyone else to pick up on once it becomes legacy.

Is there a more elegant solution to this? When you get into thousands of rules that change fairly frequently it becomes a real bear, but this cannot be that uncommon of a problem that someone has not thought of a better way to do this. Any suggestions? Is this current method defensible? What are the alternatives?

Edit: Just to clarify, this is a large enterprise app, so no matter which solution works, there will be plenty of people constantly maintaining its rules and data (around 10). Also, The data changes frequently enough to say that some sort of centralized server system is basically a must.

Was it helpful?

Solution

I would use WF or Drools if you're trying to create an abstraction that non-programmers could work with to develop business rules. However, if you're dealing with programmers than the abstraction of WF isn't worth the time it takes to develop a solution, I fail to see the added value for your investment.

A database is a good way to maintain rules that might change a lot, but let me suggest a possible alternative (not necessarily better, but an alternative).

1) Separate out the business logic into its own layer (dll) -- abstracting how you're calling it with some interfaces (look at the strategy and observer patterns) i.e IRuleEvaluator.Evaluate(string myParams).

2) Now you can create discrete classes for each rule (if necessary) and accompanying unit tests.

3) Now for the Pièce de résistance, wire up everything behind the scenes in an IOC container -- the dll and the rule evaluator instance itself. This way your rule evaluator is constructed through the configuration at runtime -- nothing is hard-coded together.

This approach is very dynamic (maybe too dynamic for some tastes) -- it will allow you to have actual discrete unit tests for your all of your rules. If you need to re-deploy or change a rule, you can drop a new DLL, change your IOC configuration file, restart and verify -- or roll back the change if something is wrong -- without modifying your core code (just like a database). And unlike a database, it will keep the logic and application code under one umbrella, instead of half written in C# and half in SQL.

OTHER TIPS

There are two cases of rules I have seen. In most cases the rule itself is not very volatile (almost fixed) but the data on which decision is taken can be changed by business users. In this case simple design patterns to encapsulate each rule with reading the reference data from DataBase is usually sufficient. Then provide a frontend to change the rules reference data.

The other cases where the rule logic itself can be changed dynamically. One approach would be to use IronPython or other dynamic languages (in .Net 4) to implement the rules and load them dynamically at execution time. This is a compromise as you will still require programmers to change the rules.

If you really want rules to be editable by business users then creating DSL for your business domain is an approach to be taken. This is a complex undertaking though.

Finally using Workflow or BizTalk can help if the rules fit into transformation/orchestration patterns.

If you are designing a highly scalable "rule-based" application where rules are subjected to frequent changes from business then consider market leading BRMS products such as: 1. IBM WODM 2. FICO BLAZE Advisor 3. Drools (open source)

I have been working on large commercial applications with a BRMS approach which make them highly scalable and easy to maintain and also make them very flexible with ZERO downtime to production. It makes business happy. :)

I am assuming you weren't strictly referring to client side operations and are in .Net since you mentioned c#...

If you are on framework 4 you have the DLR (dynamic language runtime) or on any framework if you are storing the rules in sql you could also process them there or you could always use dynamic linq in the >3 frameworks or write the different functions as assemblies that can be loaded by name at runtime through an assembly load.

Not all of those are elegant in many cases, but I have had to use them all at times.

One thing that comes to mind is Windows Workflow Foundation, which can be used along with ASP.NET but would be running on the server side (so it may not be applicable to what you're doing). In Java land there is jBPM (business process management) which also runs on the server side.

Since those solutions probably wouldn't fit the bill for you, the best thing to do may be to implement those business rules in plain old code (using javascript, C#, or whatever is best for the job) and expect that the programming code will have to be updated when design changes happen. Using object-orientated design patterns will make the code easily extendable. If you write the code well, the effort needed to change it in the future should be minimal.

If your rules are all of a form

if <condition>
then <action>
[else <action]

You could use Drools.NET or another Rete implementation such as iLog.

Licensed under: CC-BY-SA with attribution
scroll top