Business Rules Engines
-
Upload
nicolas-ohm -
Category
Documents
-
view
222 -
download
0
Transcript of Business Rules Engines
Programming with the Microsoft Business Rules Framework
Business Rules are pervasive in software. In fact, in most cases, business rules are the very
reason for the existence of most software today. As application architectures have become more and
more sophisticated, few can disagree with the merits of separating the presentation layer from the
business layer or the data layer from the business layer. Yet many applications today are still
built with process logic and business rules interwoven within the same business/application layer,
which can lead to applications that are brittle, hard to maintain, and resistant to change. In this
article, I will explain how to decouple the business rules within your application in a manner that
yields high organizational visibility and accountability; and promotes rules as a unit of reuse to
help you build applications that are ready for change.
When Rod Paddock and I first started talking about ideas for this article, my goal was to share
some of the techniques I have successfully implemented for exposing the Microsoft Business Rules
Engine (BRE) via services. Always the wise pragmatist, Rod suggested that I first start with an
introduction. If my experience delivering two talks on the subject this year at Austin Code Camp
and Desert Code Camp in Phoenix are any indication, he's probably right. Both sessions were well
attended, and most attendees had heard of rule-based engines, but had not taken it much further.
This intrigues me, because there is a growing developer community that really understands the
benefits of dependency injection, inversion of control, and contract-first development. I think
that anyone interested in such techniques should look closer at rule-based engine technology
because it is a way to accomplish or, at the very least, compliment many of these techniques. So,
while my initial goal of going deeper with the technology will have to wait, I hope that you will
discover how valuable (and cost effective) incorporating a rule-based engine into your solution
architecture and design can be.
What Are Business Rules?
The Business Rules Group, a non-commercial organization that helps to define and disambiguate the
definition of business rules defines a business rule as "a statement that defines or constrains
some aspect of the business. It is intended to assert business structure or to control or influence
the behavior of the business." The Business Rules Group further defines business rules as
organizational "guidance that there is an obligation concerning conduct, action, practice, or
procedure within a particular activity or sphere."
"
______________________________________________________________________________________________
The industry has widely accepted as best practice to separate the data layer from the business
layers.
______________________________________________________________________________________________
"
To take a practical example, a business rule may read like this:
"If the customer is a preferred member, always apply a 10% discount on the total checkout price."
Take a moment and re-read the Business Rule Group's definition in the first paragraph above. With
this perspective, the significance of this rule is profound. With very little knowledge about the
business, it is evident that the company sells products or services to individuals, and elite
customers who hold a membership status are entitled to receive a 10% discount on purchases. This
rule is likely part of an organizational customer loyalty and marketing strategy, as the business
rule is almost certainly designed to motivate customers to pay an annual premium for membership
status. At a minimum this rule governs the activity of purchasing goods by influencing the behavior
of preferred members to purchase higher-dollar purchases since they will be modestly discounted.
This is only one example. Think about the business rules that govern the applications you have
built in the past or the project you are currently on. As developers, we wield incredible power-and
responsibility-for ensuring that these business rules are elicited, developed, deployed, and
maintained as accurately and efficiently as possible. As you can imagine from the example, there
are a number of team roles that come into the lifecycle of a business rule, yet as developers we
tend to hide these rules in the bowels of code bases that will rarely if ever be visible to other
team roles, and when we are asked to change or remove a rule after the application has been
deployed we naturally resist. Why!? Because change is hard unless your application is built to
evolve, and if there is one area of your application that is almost guaranteed to change, it is the
business rules. Business rules need to be dynamic just like the business itself. Rule-based engines
allow you to harness this change by making business rules management completely transparent across
all interdependent team roles while providing very high run-time performance. In addition to
visibility and performance, rule-based engines support the loosely coupled integration of business
rules into applications that use them.
Rule Engine Fundamentals
All rule-based engines are similar in that they allow various roles within an organization to
author, save, deploy, and interact with business rules in a centralized manner that allows
disparate applications to consume the rules in a managed, service-oriented manner. As such, most
rule-based engines provide a rule editor, which allows you to author and save business rules; a
shared rules repository for persisting and looking up rules; a high-performance rules engine for
executing rules in the repository; and administrative tools for deploying, retiring, and migrating
rules from one rule repository to another.
How We Got Here
Since the dawn of computing, our forefathers and contemporaries alike have been hard at work
chipping away at the same problem: how to break apart the monolith by decoupling as many components
as possible without sacrificing performance. Ever since the first computer, the trend has been
constant. Computing has moved from sprockets and dials to assembly languages and onto procedural,
object-oriented, component-oriented, and service-oriented designs, which further lubricate
interaction between constituent parts of a system. Each of these evolutionary technologies has
ushered in refined architectures such as 2-tier, n-tier, and service-oriented architecture.
The industry, in building scalable systems that are also maintainable, has widely accepted as best
practice to separate the data layer from the business layers. The user interface and business
layers have evolved as well, making the logical separation of user interfaces and business layer
physical with the advent of distributed component technologies. Even platform and vendor coupling
has proven to be undesirable, and today components can communicate with one another using messaging
standards sanctioned by non-proprietary standards bodies such as W3C and Oasis.
With business rules being such a critical part of any application architecture, there are likely
great opportunities for decoupling business rules from the main application or process layer.
Often, the idea with decoupling is that the less one component or service knows about the other,
the more free each component or service is to change and evolve. The same is true for business
rules, and this is the heart of the case for using a rule-based engine.
Why Use a Rule-based Engine?
A rule-based engine isolates business rules from the application making the rules eminently
reusable. Since business rules are (or should be) organizationally universal-as opposed to
application specific-rule-based engines can provide unprecedented reuse (another goal of
decoupling) of business rules. In addition, business rules that are visible to mere mortals
(non-developers) are much better understood and this transparency introduces higher accountability
within teams. In software development, a team is not just comprised of developers and architects.
While these roles are very important, software product development includes stakeholders,
line-of-business managers, business analysts, and quality assurance analysts to name just a few.
A recent report in CIO Magazine found that up to 70% of CIO budgets are spent on maintenance. Even
conservatively, if you assume that half of the maintenance costs are attributed to business rules
maintenance; it is likely that upward of 35% of IT budgets are spent managing business rules. A
recent report by IDC supports these numbers. According to IDC, three-year net ROI for organizations
deploying rule-based engines is in excess of 100% through 25%-80% reductions in development costs.
The report goes on to cite increases in profitability and decision-making outcome of up to 50%.
The reason for the increase in productivity and ROI is simple. Separating business rules from
programming code allows non-programmers to maintain business logic without writing code. Even for
the most talented developers, writing code is expensive and error prone (if you have any doubts
about this assertion, please see Test-Driven Development). The ability for interdependent team
roles to have a hand in business rule management naturally reduces the time, risk, and effort
inherent to programming changes to business rules in a vacuum. Shared business rule management
leads to reduced development schedules and lower maintenance costs.
In addition, extracting business rules and making them available to the wider team promotes
visibility and understanding of business policies and procedures, which serves to promote
consistent decision making which leads to profitability. Fair Isaac, a leading rule-based engine
vendor corroborates these assertions, reporting that in interviewing hundreds of customers
throughout the world, "a 25% compression of development time is quite common, along with cost
savings for developing new applications of up to 80% and maintenance of applications of up to 75%".
Another great benefit to isolating business rules is that it makes them eminently testable. This is
a core value that any Test-Driven Developer holds dear, and a business rules engine can be thought
of as a way to provide a different kind of dependency injection to your applications.
Introducing Microsoft Business Rules Framework
The Microsoft Business Rules Framework is a fully functional rule framework originally intended for
plugging in various rule executors and translators. The Microsoft Business Rules Engine is
Microsoft's implementation of their own rule language and corresponding translator components as
well as execution components based on the Rete algorithm (defined later) that plug in to the
Microsoft Business Rules Framework and is commonly referred to as the Microsoft Business Rules
Engine (BRE).
"
______________________________________________________________________________________________
A rule-based engine isolates business rules from the application making the rules eminently
reusable (and not to mention testable).
______________________________________________________________________________________________
"
While the Microsoft Business Rules Framework and BRE are still relatively new (both were originally
released with Microsoft BizTalk Server 2004), the Rete algorithm is not. The Artificial
Intelligence Journal published a paper by Dr. Charles L. Forgy in 1982 entitled "Rete: A Fast
Algorithm for the Many Pattern/Many Object Pattern Match Problem". Dr. Forgy first published his
research work on the Rete algorithm in 1974 as a an efficient pattern-matching algorithm which is
capable of evaluating rules at a very high rate of speed with little regard for the number of rules
being considered. The algorithm works by cross-checking a business fact with business policies to
determine which rules should be considered for execution. If a rule does not need to be considered,
it is skipped altogether. Also known as an inference-based rules engine, the Microsoft BRE also
supports forward chaining of business rules which causes the BRE to re-evaluate rules in a policy
when the action of a rule that has fired causes a change to the state of a fact that has otherwise
already been asserted.
Although the Microsoft Business Rules Framework (and MS BRE) ships with Microsoft BizTalk Server
2004, 2006, and 2006 R2, this is where any association to BizTalk Server ends. Microsoft defines
the Business Rules Engine as a stand-alone application that consists of a number of modules,
support components, and tools. What you get out of the box is Microsoft's implementation of
pluggable components which, in conjunction with the Business Rules Framework, is commonly referred
to as Microsoft BRE. The primary modules include the Business Rules Composer for constructing
policies, the Rules Engine Deployment Wizard for deploying policies created in the Business Rules
Composer, and the Run-Time Rule Engine that executes policies on behalf of a host application. I
will look at these modules in more detail as I apply a practical example of how to create a
business rule within a policy, and call it from a .NET application.
What it Isn't
As I mentioned before, the MS BRE has nothing to do with BizTalk Server. It ships and is installed
with BizTalk Server but you can take full advantage of MS BRE without BizTalk Server messaging or
orchestration. This means that if you choose to only install MS BRE on a machine, you can do so
with a very small footprint. However, keep in mind that since MS BRE is not a separate SKU, you can
only get it with BizTalk Server, and as such, you must meet licensing requirements for BizTalk
Server even if you only use MS BRE. While this may sound intimidating, doing any amount of market
research on competing rule-based engines will quickly prove that the price point in which Microsoft
places the Developer and Standard editions of BizTalk Server 2006 better makes MS BRE a compelling
choice for bringing a fully functional rules engine into the enterprise.
In addition, MS BRE has nothing to do with Windows Workflow Foundation (WF) Rules. While there are
similarities, it is important to understand that MS BRE is a product that is developed, maintained,
and supported by a different product team inside Microsoft. WF is not a product. WF is a framework
for building workflow enabled applications and services. WF supports the execution of business
rules; however, the features provided in WF Rules in the current shipping version of .NET 3.5 pale
in comparison to MS BRE. WF Rules lacks a rule editor that can be used outside of the developer
role and lacks a rule repository. Like most of the features in WF, this makes WF Rules a solid
starting point for building out additional rule-based engine functionality, but at its core merely
provides an engine which is capable of executing rules. In fact, in early drops of WF, WF workflows
were calling Microsoft BRE to demonstrate proof of concept scenarios before WF Rules were fully
baked. While Microsoft has not taken a position on the future of each offering, I can only
speculate that these competing offerings will converge, perhaps as part of the Oslo vision. Until
then, I believe, and others agree (please see sidebar "Comparing Microsoft BRE and WF Rules") that
MS BRE is a stronger choice for integrating rule-based engines into your applications and services.
Microsoft Business Rules Framework Architecture
The architecture for MS BRE is comprised of design-time and run-time components. As shown in Figure
1, design-time components that include the Business Rules Composer are provided via a separate user
interface (outside of Visual Studio) to manipulate the Vocabulary, Rule Store, and Rule Set object
model. While the BRE is a first-class citizen in BizTalk Orchestration, I will work exclusively
with the Business Rules Composer and Visual Studio 2008 to develop, test, and execute the rule set
in this article.
Click for a larger version of this image.
Figure 1: The Microsoft Business Rules Framework consists of design-time and run-time components.
Diagram courtesy of Microsoft Corporation.
The Vocabulary Object Model allows developers and business analysts to use the Business Rules
Composer to create domain-specific definitions for data, or facts that are represented in various
states.
The Rule Set object model allows for developers and analysts to build the rules that will consist
of raw facts that can be either XML message-based, any .NET object, or a field in a database table
or in-memory dataset. Rules are grouped according to business domain and are logically organized as
Policies. For example, you may have a rule that states that "If the customer is a preferred member,
always apply a 10% discount on the total checkout price". This rule might be just one rule in a
rule set that is logically represented as the discount policy for the company.
Once vocabularies and policies/rule sets are created, they need to be persisted to the Rule Store,
and the Business Rules Composer uses the Rule Store object model to do so. By default, the Rule
Store is a SQL Server database; however, it is possible to use a file or other backing store (with
some elbow grease, of course). Using SQL Server as the default repository for policies and
vocabularies has some obvious performance and management benefits. Rules and vocabularies are
serialized to BRL (Business Rules Language), which as you might imagine is an XML representation of
the policy and rules.
From a run-time perspective, an application, such as a Smart Client, Console, WCF Service, WF
application, or BizTalk Orchestration, works with a Policy class that provides the integration glue
with the BRE. The Policy works with an instance of the Rule Engine class, thus shielding the
developer and application from intimate details about the BRE itself.
The Rule Engine class is the workhorse behind the BRE and is responsible for the execution of the
business rule policies. The Rule Engine class takes a policy (rule set) name as an argument, along
with corresponding facts and determines which rules are applicable given the facts, translates the
rules from BRL to in-memory object graphs, and executes the appropriate rules. I will cover this in
more detail later, but it is important to understand that every rule has a condition, predicate,
and action. This means that given our now canonical rule ("If the customer is a preferred member,
always apply a 10% discount on the total checkout price"), if the rule executes, and the condition
in the rule evaluates to true, the 10% discount will be performed.
Finally, a Windows Service, known as the Rule Engine Update Service, monitors the Rule Store for
changes to rules or policies. If there is a change, the Rule Engine Update Service updates the Rule
Engine's local cache to ensure that Rule Engine instances that are bound to a live Policy instance
are updated in real time, and to also ensure that any subsequent Policy invocations use an instance
of the Rules Engine that is synchronized with the Rule Store.
The magic of the BRE is that it performs well because it is inference based. What this means is
that the BRE will only consider rules that apply to a given fact. Instead of looping through
dozens, hundreds, or thousands of rules, the BRE creates an agenda of rules to execute that are
associated with the fact. This could be a single rule or several. Once the rules are added to the
agenda, they are executed one by one until the execution cycle terminates. This means that you
might have one or several corresponding actions resulting in a number of rules firing. I'll cover
agenda and priority and provide an example of forward chaining towards the end of this article.
BRE Roles
As discussed, it takes much more than sheer programming to build a software product, and one of the
main objectives of the Microsoft Business Rules Framework is to help lubricate communication and
collaboration between team members in various yet intersecting roles. By using the Business Rules
Composer, all team roles can work together to implement the rules as part of a policy that makes
sense in a business context and is verifiable and traceable by all. While I will not go on a rant
about the merits of Domain Driven Design here, the power of sharing a common language and taxonomy
with your entire team is a tremendous boost to productivity, comprehension, and morale.
"
______________________________________________________________________________________________
Software product development teams also include stakeholders, line of business managers, business
analysts, and quality assurance analysts to name just a few.
______________________________________________________________________________________________
"
Once your rules and policies have been authored and tested, they can be deployed in a development
environment by anyone with access to the Business Rules Composer. However, in Staging and
Production environments it is likely that a release engineer or an administrative member of a
deployment team will be responsible for pushing out new policies and updated existing policies by
introducing a new policy version. This is precisely what the Deployment Utility is for.
Coming to Terms
I have already covered many of the following terms in this discussion, but let me provide some
precise definitions by example for clarity sake. Hopefully, after reading this article, you will be
well versed in the lingua franca that makes up the Microsoft Business Rules Framework.
Policy
A Policy is a versioned logical grouping of rules. It is represented by the Policy class, which
allows a calling component to execute a corresponding rule set that is bound to the policy. For
example, a discount policy would consist of rules about how and when to apply discounts to purchase
orders. You create a Policy using the Business Rules Composer, and execute a policy via the Policy
class. Policies are versioned, and once a version has been deployed, the policy is immutable. This
ensures that a policy version remains sacrosanct, and also supports concurrent policy versions.
Rule
A rule is a statement that consists of a condition and actions. Rules are commonly created within
the Business Rules Composer. A rule consists of a condition that evaluates facts and a
corresponding action to take if the condition evaluates to true. If the preferred member condition
is met, then the corresponding action will be to apply a 10% discount to the purchase. It is
possible to program directly with the Rule class, but in this article you will build rules using
the Business Rules Composer and execute rules by using the Policy class.
Condition
A condition simply consists of predicates that apply to a fact, and always returns true or false.
Examples of predicates are between, greater than, less than, equal to, etc.
Facts
Fundamentally, a fact is in-memory data that is acted upon within the BRE. For example, a Customer
object is a memory type that contains information about a customer. The information is represented
as public properties, such as First Name, Last Name, and Preferred Member. These fields are
referred to as "fact slots" which are then used in conjunction with a condition and action to form
a rule. In the example, the "preferred member" fact would map to the Preferred Member fact slot on
the Customer fact.
Fact Types
There are actually two types of facts. Short-term facts are passed into the Policy object and
removed from memory as soon as a policy completes execution. Short-term facts are introduced to the
Policy class as .NET objects, XML document instances, or database rowsets. Long-term facts remain
in memory across multiple execution cycles. An example of a short-term fact might be the Customer
instance passed into the Policy instance, while a long-term fact might be the standard shipping
rate to apply. Since the standard shipping rate seldom changes, this is an excellent candidate for
a long-term fact, which is cached in memory to be reused throughout rule-engine execution cycles.
In addition, long-term facts can be configured to refresh cache as necessary.
Actions
An action is the consequence of a rule being executed within a policy that yields a true condition
evaluation. The action results in a function call that is wired up within the Rules Engine
Composer. For example, given a customer who is a preferred member, the action may be to set the
Discount Percentage field on the Customer fact itself. This is just one of several possible
actions.
Vocabulary
A vocabulary is simply a set of user friendly business definitions in the language of the domain
that map to a fact or fact slot. For example, the preferred member status of a customer may be
represented in SQL as "SELECT MembershipStatus from Customers WHERE LastName= "Deniro". While this
statement may be pretty straightforward, for non-developers, the T-SQL syntax may not be as
intuitive. You can use a vocabulary to define the fact and give it a friendly name such as
"MemberStatus". Now developers and non-developers can have domain-specific conversations in
building a business rule around pricing models for customers who are members.
Installing and Working with the Microsoft Business Rules Engine
Please don't let the fact Microsoft BRE ships with BizTalk Server intimidate you. While BizTalk
Server is indeed a robust server platform that requires experience to install and configure, the
installer for BizTalk Server 2006 and later has been significantly streamlined compared to previous
versions, and installing the Business Rules Engine is very straightforward.
"
______________________________________________________________________________________________
Up to 70% of CIO budgets are spent on maintenance.
______________________________________________________________________________________________
"
In fact, as you'll learn below, you can install the BRE completely independently of other BizTalk
components, making installation a breeze:
1. Simply start the BizTalk Server 2006 or 2006 R2 installer and click "Install Microsoft BizTalk
Server on this computer" as shown in Figure 2.
2. On the Component Installation screen, clear all options except "Documentation" and "Business
Rules Components", and then click Next as shown in Figure 3.
3. As shown in Figure 4, you will see a Summary screen that summarizes the fact that you are only
installing documentation and core components necessary for the BRE. Click "Install" to begin
installation.
4. After a few moments, you will be presented with an Installation Progress screen which will take
a couple of minutes to complete. Once complete, you will be presented with a corresponding
screen as shown in Figure 5. Make sure to check "Launch BizTalk Configuration" and click Finish
to begin configuring BRE.
5. The BizTalk Server 2006 configuration screen appears. As shown in Figure 6, make sure to select
"Basic configuration", confirm the name of the machine on which you are performing the
installation/configuration, and enter credentials that will be used to run the Rule Engine
Update Service. Click Configure, and you should see a list of components identical to Figure 7.
6. Click Next and, in a few moments, configuration should complete and succeed as shown in Figure
8.
Click for a larger version of this image.
Figure 2: To install Microsoft BRE, simply launch the BizTalk Server installer.
Click for a larger version of this image.
Figure 3: Installation of the Microsoft BRE and corresponding Business Rules Framework simply
consists of selecting the Business Rules Components option.
Click for a larger version of this image.
Figure 4: The Microsoft Business Rules Framework is installed automatically by selecting the
Business Rules Components. These are the only components required to begin using Microsoft BRE
immediately; however, the product documentation is also recommended.
Click for a larger version of this image.
Figure 5: Following installation, it is necessary to configure the Microsoft BRE components.
Click for a larger version of this image.
Figure 6: Configuration is very simple and only requires a host name and account credentials for
the Rule Engine Update Service.
Click for a larger version of this image.
Figure 7: The Summary lists the components that will be configured.
Click for a larger version of this image.
Figure 8: The Microsoft BRE is installed successfully in a matter of minutes.
A gentle reminder: Please remember that although the Microsoft Business Rules Framework and BRE
components are fully functional in a standalone configuration, any machine running BRE, or any
other BizTalk Server components must be fully licensed for BizTalk Server 2006 or better.
With the Microsoft Business Rules Framework, and Microsoft Business Rules Engine installed, you are
ready to create your first policy!
Creating and Deploying a Policy with the Business Rules Composer
I am going to continue working with the same business rule I've used in previous discussions.
Without knowing anything about the business domain, by simply reading the rule in plain English, it
is evident that I am dealing with a customer and purchase domain.
"
______________________________________________________________________________________________
According to IDC, three-year net ROI for organizations deploying rule-based engines is in excess of
100% through 25%-80% reductions in development costs.
______________________________________________________________________________________________
"
Both of these entities are fundamental for composing the business rule and for BRE execution,
because the rule must first determine if the customer is a preferred member, and if so, apply a 10%
discount to the purchase order.
Figure 9 shows a model of the Customer and PurchaseOrder entities, and the code for each entity is
provided in Listing 1 and Listing 2 respectively. Recall that the BRE can work with XML, a database
or .NET objects, and in this case, since I am modeling the domain by using C# classes as my domain
entities, I will simply use these same objects when working with the BRE.
Click for a larger version of this image.
Figure 9: The Customer and Purchase Order business entities are used to model the business domain.
The sample code that I've prepared for this article (please refer to sidebar "Solution Download"
for download instructions) contains three projects:
1. Acme.RetailOperations: Represents the application or process layer of a sample application.
2. Acme.BusinessEntities: Contains the Customer and PurchaseOrder entities previously discussed.
3. Acme.RetailOperations.Tests: Contains unit tests that allow us to emergently build our
application layer.
4. Once you download the solution, I would encourage you make a copy of the MSBRESample.zip file,
unzip it, open the MSBRESample.sln and delete the contents of the PurchaseService.cs file in
the Acme.RetailOperations project as well as the contents of the PurchaseServiceTests.cs file.
There isn't much code to write, but I want to show you how powerful Test-Driven-Development
coupled with the Microsoft Business Rules Engine can be in not only decoupling the business
rules from your application layer, but also in writing just enough code to get the job done.
5. I have also provided all code listings, so you should also be able to follow along without
firing up Visual Studio.
6. First, I'll write a test method to exercise the application for correctly adhering to the 10%
discount rule for customers with a preferred membership status.
7. I stubbed out the following test method called
"ExecuteCustomerCheckOutDiscountAmountShouldBeTenPercent". The name of the test method tells me
two things: First, I am exercising the CustomerCheckOut method on the PurchasingService, and
second, I expect that the DiscountAmount property on the customer instance is 10% as shown in
Listing 3 which provides the unit test code
Of course, when I try to compile my Acme.RetailOperations.Tests project, I get a bunch of
compilation errors because the CustomerCheckOut method doesn't exist yet.
Pop into the empty PurchaseService class and write enough code to at least get the unit test to
compile. Listing 4 shows the contents of my very primitive CustomerCheckout method implementation,
but remember, the goal at this point is to write just enough code to compile the unit test as shown
below:
namespace Acme.RetailOperations
{
public class PurchaseService
{
public void CustomerCheckout(Customer customer)
{
// some logic
}
}
}
At this point, the unit test compiles but if you run it, it should fail because in setting up the
Customer and PurchaseOrder within the unit test, I've initialized the DiscountPercentage to 0%.
Despite the PreferredMember property being set to true, there is no business rule or policy for
acting on this (the body of the CustomerCheckout method is empty), and as expected, the test fails
as shown in Figure 10.
Click for a larger version of this image.
Figure 10: The unit test fails because the Microsoft BRE policy has not yet been integrated into
the application layer.
The goal now is to write enough code to get the test to pass. In order for the test to pass, you
need to enforce the business rule, and you'll use the Microsoft BRE to do just that.
Start the Business Rules Composer by going to Start > Program > Microsoft BizTalk Server 2006 >
Business Rule Composer as shown in Figure 11. In the upper left-hand corner, you will find the
Policy Explorer. Right-click the Policy root and click "Add New Policy" as shown in Figure 12.
Provide a name for the policy that is intuitive and representative of the business domain, such as
"Customer Discounts Policy". As shown in Figure 13, you will notice that the Policy has been
automatically versioned to 1.0. Right-click the version, select "Add New Rule", and name the rule
"Preferred Member Customer Discount".
Click for a larger version of this image.
Figure 11: The Business Rules Composer is started from the Microsoft BizTalk Server 2006 program
group.
Click for a larger version of this image.
Figure 12: Adding a new policy allows you to group business roles according to domain-specific
groups.
Click for a larger version of this image.
Figure 13: Once a new policy is created, it is versioned and cannot be changed once deployed to the
repository.
On the right pane is a surface area on which to build your condition. As you might imagine, this is
simply an "If" statement with some predicates. Select the "Equal" predicate as shown in Figure 14.
You will use the equality predicate to determine if the customer is a preferred member.
Click for a larger version of this image.
Figure 14: The equality predicate is just one of several predicates for building conditional
business rules within the Business Rules Composer.
To do so, you need to tell the BRE which fact slot will contain the data that determines if the
customer is a member, so under Fact Explorer, click the .NET Class tab, right-click ".NET
Assemblies", and click Browse. As shown in Figure 15, a list of assemblies appears. The list is an
enumeration of the assemblies in the Global Assembly Cache, which is a requirement for .NET objects
that will be used as facts (if you have not already done so, add the Acme.BusinessEntities.dll
assembly to the GAC prior to browsing for it). Select the Acme.BusinessEntities.dll and click OK.
Click for a larger version of this image.
Figure 15: Assemblies containing facts to be asserted must be added to the Global Assembly Cache
(GAC).
Both Customer and PurchaseOrder classes are enumerated under the ".NET Assemblies" root, and if you
expand the Customer class, you will find assessors for all public properties, including the
PreferredMember property as shown in Figure 16. Drag the PreferredMember get accessor to the
Condition surface area and drop onto Argument 1. The condition should now look like Figure 17. Now,
click "Argument 2" and type "true" without the quotes as shown in Figure 18. You now have a full
condition that inspects the PreferredMember fact slot on the Customer fact and tests the value for
equality to true. Recall that a condition will always result in a Boolean value.
Click for a larger version of this image.
Figure 16: Facts consist of fact slots, which in the case of .NET types include assessors for
working with the fact.
Click for a larger version of this image.
Figure 17: An equality predicate requires two arguments. The first argument is provided by dragging
and dropping the corresponding fact slot from the Customer fact.
Click for a larger version of this image.
Figure 18: A condition is simply an If/Then statement that will always result in true or false.
With the condition complete, all that is left is to provide the BRE with an action to execute when
the condition is true. In this case, you simply want to set the DiscountPercentage property on the
PurchaseOrder fact to 10%. Drag the DiscountPercentage set accessor from the PurchaseOrder fact and
drop it on the Actions design surface. Figure 19 shows the compete rule with conditions and
corresponding action that should fire if the condition evaluates to true.
Click for a larger version of this image.
Figure 19: A business rule is the combination of the condition and action should the condition
evaluate to true.
Note that creating vocabulary definitions are useful for creating friendly names for otherwise
esoteric facts and fact slots. For example, if you are using an XML message as a fact and have a
complex XPath query to map a condition argument to a fact slot, you may quickly defeat the purpose
of exposing your rules in a way that supports inter-role collaboration. The solution to this
dilemma is to create vocabulary definitions that act as aliases for fact slots that would otherwise
be unreadable to the non-developer (even I detest reading XPath statements!). Since you are using
.NET types that are modeled after the business domain, I have skipped creating vocabulary
definitions altogether.
"
______________________________________________________________________________________________
If there are two or more rules that use the same fact slot in the condition, the BRE will determine
execution order based on priority.
______________________________________________________________________________________________
"
At this point, you have successfully created the "Preferred Member Customer Discount" rule within
the "Customer Discounts Policy" policy. Right-click the policy and save the rule.
Recall that a policy can contain one or more rules, and as such the policy is the logical unit of
deployment. Also recall that policies are versioned and once a policy has been deployed, it is
immutable. Therefore, before you publish and deploy the policy, you need to test it.
Testing a Policy by Implementing the IFactCreator Interface
As I've discussed, at run time, each of these facts and fact slots will be asserted into the BRE
and the BRE will determine which rule(s) to add to its agenda based on the presence of facts. For
testing purposes, it is necessary to provide the Business Rules Composer with a hydrated instance
of the Customer object which it will use to determine which rules should be added to the agenda. To
hydrate an instance, you must first create what is called a "Fact Creator".
"
______________________________________________________________________________________________
Dr. Forgy first published his research work on the Rete algorithm in 1972 as an efficient
pattern-matching algorithm which is capable of evaluating rules at a very high rate of speed.
______________________________________________________________________________________________
"
Creating a Fact Creator is extremely straightforward, and simply entails implementing the
IFactCreator interface on a class to provide a surrogate Customer class to the BRE using a
prescribed interface.
The CustomerFactCreator class, shown in Listing 5 shows the implementation of the IFactCreator. The
CreateFacts method fulfills a contract to return an array of objects. These objects are the facts
that are used by the BRE to conduct a pre-deployment test. In this case, I have simply copied and
pasted the Customer and PurchaseOrder initialization code from the unit test to the CreateFacts
method, created a single dimension array to hold the Customer instance, and fulfilled the contract
by returning the array.
With the Acme.BusinessEntities.dll in the GAC, right-click "Version 1.0" of the Customer Discounts
Policy, and then select "Test Policy" as shown in Figure 20. A screen appears which allows you to
select the CustomerFactCreator. Click "Add", select the Acme.BusinessEntities.dll from the list of
.NET assemblies, and then click "OK". The Business Rules Composer will query the assembly for any
Fact Creators and enumerate them. As shown in Figure 21, select the CustomerFactCreator and click
"OK".
Click for a larger version of this image.
Figure 20: The Business Rules Composer includes an integrated tool for testing condition behavior
and agenda plan.
Click for a larger version of this image.
Figure 21: A Fact Creator must be supplied to the Business Rules Composer testing tool to assert
the required facts for execution.
Now click "Test". Immediately, the agenda results are displayed in the test output pane as shown in
Figure 22.
Click for a larger version of this image.
Figure 22: Agenda results are output immediately following the assertion of test facts into the
BRE.
Understanding Agendas and Priority
Now I want to look at the test results of the Customer Discounts Policy test by reviewing the
agenda results in Figure 22.
You used the CustomerFactCreator to assert the Customer instance as a fact to the BRE. The BRE then
looked for any rules that contain conditions which map to fact slots that are present in the fact
that was asserted. Because the Customer indeed contains a field which indicates if the sample
customer is a preferred member, the rule was added to the agenda and executed. The condition
evaluated to true, because the PreferredMember fact slot on the Customer fact was set to true in
your CustomerFactCreator. Since the Customer was asserted as a short-term fact, and there are no
other rules in the policy, the Customer instance is removed from memory and the BRE execution cycle
terminates.
If there are two or more rules that use the same fact slot in a condition, the BRE will determine
execution order based on priority. Priority is set on each rule within the Business Rule Composer.
A rule with a higher priority fires first.
This has been a good test for testing that the condition of your rule is behaving as expected, and
that the agenda is loading rules according to the expected priority, but you still don't know if
the action is working as designed. There is no good way to do this within the Business Rules
Composer.
Fortunately, you have a unit test in your Visual Studio solution that is up for the job!
Calling a Policy Programmatically
With the test complete, right-click Version 1.0 of the policy, click "Publish", and then click
"Deploy" to deploy the policy to the repository as shown in Figure 23. You will notice that you can
no longer modify the policy by editing existing rules, removing rules, or adding new ones. Since
the policy has been deployed, you cannot change it without creating a new version of the policy.
Click for a larger version of this image.
Figure 23: Policies can be deployed to the repository directly from the Business Rules Composer or
using the BRE Deployment Utility (not shown).
Recall that although your ExecuteCustomerCheckOutDiscountAmountShouldBeTenPercent unit test
compiles (Listing 3), the last time you exercised it, it failed. It failed because there is no
implementation to the CustomerCheckOut method skeleton and therefore, the DiscountPercentage is
zero just as it was before the test ran.
"
______________________________________________________________________________________________
The Rule Set object model allows for developers and analysts to build the rules that will consist
of raw facts, which can be either XML message-based, any .NET object, or a field in a database.
______________________________________________________________________________________________
"
Jumping back into Visual Studio, in the Acme.RetailOperations project, right-click References and
add a reference to the Microsoft.RulesEngine.dll which contains everything that you need to
integrate the Microsoft BRE into your application. The Microsoft.RuleEngine.dll assembly resides in
the C:\Program Files\Microsoft BizTalk Server 2006\ folder as shown in Figure 24.
Click for a larger version of this image.
Figure 24: Programming with the Microsoft BRE is as simple as adding a reference to the
Microsoft.BusinessRules.dll assembly.
I want to focus on the enforcement of the business rule, so I am not going to spend any time on
other implementation details. You certainly might expect the CustomerCheckOut method to carry out
additional chores such as checking inventory, calculating shipping charges, and authorizing a
credit card.
With the reference to the Microsoft.RulesEngine.dll added, add the following using statement to the
PurchaseService.cs file:
using Microsoft.RuleEngine;
Listing 4 shows the contents of the PurchaseService class, which will act as your primitive
application layer.
You need to split the Customer and PurchaseOrder out into two separate facts because the BRE will
work with each fact separately. You can accomplish this by simply creating an object array and
adding the Customer instance and decomposed PurchaseOrder instance to the fact array.
With the facts ready, simply instantiate a Policy and provide the name of the policy you are
working with in the constructor. Note that you can also provide a specific version of the policy,
but if omitted, the newest policy will always be used. Now, call Execute on the Policy instance and
pass in the facts array.
When the BRE is done executing the policy, it will set the DiscountPercentage property on the
instance of the Customer class to 10% which the PurchaseService maintains a reference to. Now,
re-run the ExecuteCustomerCheckOutDiscountAmountShouldBeTenPercent unit test and it should pass
with flying colors as shown in Figure 25.
Click for a larger version of this image.
Figure 25: Once the BRE policy is integrated into the application layer, unit tests are critical to
ensuring corresponding actions behave as expected.
While this is a very simple implementation of a purchasing application layer, the loose coupling
between the application layer and the business rules is powerful indeed. Not only is there less
code to write (you've harnessed the power of a fully featured rule-based engine with two lines of
code), the discount policy is free to evolve with the needs of the business.
Suppose a decision was made to increase or decrease the discount amount for preferred members, or
to eliminate the rule altogether? Affecting this change would simply be a matter of updating the
Customer Discounts Policy within the Business Rules Composer, testing the condition, and deploying
a new policy version, all without changing a single line of code!
Understanding Forward Chaining
I have (hopefully) kept things relatively simple, and by now you should have a good understanding
of the Microsoft Business Rules Framework and BRE fundamentals. One topic I have not talked about
in detail is forward chaining.
"
______________________________________________________________________________________________
The Rule Engine class takes a policy (rule set) as an argument and determines which rules are
applicable given the facts, translates the rules from BRL to in-memory object graphs, and executes
the appropriate rules.
______________________________________________________________________________________________
"
Suppose your company introduced a new business rule that ensures that the combination of the
preferred member discount and any current sale discounts do not cause the final price to fall below
margin. This is important to ensure that the preferred membership program doesn't inadvertently
cost the company money.
Such a business rule might be: "If the discount percentage on an order would cause the unit price
to fall below margin, adjust the discount percentage accordingly."
While it may sound complex at first, it is really very simple. The only time this rule needs to be
considered is when a discount percentage is present. Non-preferred customers rarely have discounts
unless they use a discount code.
The Customer Discounts Policy would prioritize the existing rules such that the 10% discount rule
fires first, and upon the Discount Percentage fact slot being updated, the margin protection rule
would be considered. If the customer receives no discount, the Discount Percentage remains null;
however, if the fact changes as a result of a preceding rule, new rules must be considered. This
means that the BRE would complete two cycles. The second cycle would fire as a result of the
Discount Percentage fact being changed and thus a forward chaining of execution.
Summary
I have provided an overview of rule-based engine technology and Microsoft's implementation within
the Microsoft Business Rules Engine which is based on the Microsoft Business Rules Framework.
You took an emergent approach to building the customer check out functionality in your sample
application by using Visual Studio 2008 and test-first development. You worked with the Business
Rules Composer to create a policy and a rule, and tested the policy before deploying it to the Rule
Repository.
You then leveraged the .NET Microsoft BRE API to integrate the policy you created and verified the
correct behavior by running your unit test within Visual Studio.
While one of the strengths of implementing a rule-based engine is the ease of working with and
deploying rules, it is very important to understand that a rule-based engine such as Microsoft BRE
does not eliminate the need for strong application lifecycle management policies. While team and
organizational productivity will increase significantly by leveraging the BRE, the fact that
business rules can be updated with ease can also be a dangerous thing.
Organizations that effectively leverage a rule-based engine like Microsoft BRE have likely evolved
to a higher level of thinking that makes rule management service-oriented. The decoupling and
isolation of rules and policies from constituent applications fixes many old problems, but also
introduces new challenges around change management because a change in one rule can have widespread
organizational impact depending on the number of applications that integrate with the given policy.
For this reason, it is critical to maintain development, integration, and testing environments for
integrating rule changes-nothing changes here.
As an added bonus, if you and your team practice test-driven development, regression testing a
policy change should be as simple as running corresponding batteries of unit tests manually or in
the next automated build. While not a silver bullet, this is definitely one step forward in
increasing business and IT alignment because the rules are centralized, transparent, and support
flexible applications that are not only ready for change, but built for it!
"
______________________________________________________________________________________________
You can install the BRE completely independently of other BizTalk components, making installation a
breeze!
______________________________________________________________________________________________
"
One final word of advice: It is very important to understand that despite the compelling
productivity improvements that deploying Microsoft BRE will bring, I do not recommend embarking on
a project whose sole purpose is to integrate a rule-based engine within the enterprise. Such a
project is doomed to fail because technology projects for technology's sake rarely provide
convincing evidence that there is value in the undertaking in and of themselves. The key with any
software or IT project is to focus on delivering business value. Services, SOA, and high-performing
rule engines like Microsoft BRE are merely a vehicle for doing so. Don't confuse the two.
The CHAOS report (see sidebar) finds that 13% of features in an application are often used, and 7%
of features are always used. My advice to you is to work with the business members of your team to
identify the 30% sweet spot and start with a business process or business rule or two. By taking a
middle-out approach, you are bound to quickly and easily find processes for which introducing this
flexibility would add significant business value. Think big, start small, prove your business case
and the rest will follow.
Rick Garibay
&
[ArticleImage.aspx?QuickID=0811071&MaxWidth=150&Image=author:5a9ce65b-d576-4b28-9b47-6e569e
b3bab8]
By: Rick Garibay
With over 13 years' experience delivering solutions on the Microsoft platform across industry
sectors such as finance, transportation, hospitality and gaming, Rick is a developer, architect,
speaker and author on distributed technologies and is the General Manager of the Connected Systems
Development Practice at Neudesic.
Rick specializes in distributed technologies such as Microsoft .NET, Windows Communication
Foundation, Workflow Foundation, and Windows Azure to deliver business value and drive revenue
while reducing operational costs.
Rick serves as a member of the Microsoft Application Platform Partner Advisory Council and is an
advisor to Microsoft in a number of capacities including long-time membership on the Business
Platform and Azure Technology Advisors group. As a five-time Microsoft Connected Systems MVP, Rick
is an active speaker, writer and passionate community advocate in the national .NET community. Rick
is the Co-Founder of the Phoenix Connected Systems User Group, celebrating four years in operation.
Recent presentations include talks at the Microsoft SOA and Business Process Conference in Redmond,
WA, Microsoft TechEd, DevConnections, .NET Rocks, Desert Code Camp, and numerous Microsoft events
throughout North America. Rick is a frequent contributor to industry publications such as CODE
Magazine, and is the co-author of Windows Server AppFabric Cookbook by Packt Press.
When not immersed in the work he loves, Rick enjoys mountain biking and spending time with his
wife, Christie and two children, Sarah and Ricky.
Fast Facts
A business rule is a statement that defines or constrains some aspect of the business. It is
intended to assert business structure or to control or influence the behavior of the business.
Emergent Development
Scott W. Ambler presents some compelling facts about the inevitability of change in our software
applications: http://www.agilemodeling.com/essays/examiningBRUF.htm
Comparing Microsoft BRE and WF Rules
Perhaps one of the most knowledgeable rule-engine enthusiasts on the planet, Charles Young has
written several articles about the Microsoft Business Rules Framework, Microsoft BRE, and Workflow
Rules.
You can learn about the performance benefits of Microsoft BRE along with strengths and liabilities
of each offering and much more by visiting Charles's blog:
http://geekswithblogs.net/cyoung/archive/2007/08/12/114597.aspx
MSDN Documentation
Complete documentation for the Microsoft BRE is available on the MSDN Network:
http://msdn.microsoft.com/en-us/library/aa577691.aspx
On the Rete Algorithm
More information regarding the Rete algorithm is available on the PST Web site:
http://www.pst.com/rete2.htm
Solution Download
You can download the code for this article at http://rickgaribay.net/
______________________________________________________________________________________________
Click here for a text-only version of this listing. Listing 1: The Customer Domain Entity.
using System;
using System.Text;
namespace Acme.BusinessEntities
{
/// <summary>
/// Encapsulates elements used to describe a customer.
/// </summary>
public class Customer
{
private string m_FirstName;
private string m_LastName;
private bool m_PreferredMember;
private PurchaseOrder m_Order;
public string FirstName
{
get { return m_FirstName; }
set { m_FirstName = value; }
}
public string LastName
{
get { return m_LastName; }
set { m_LastName = value; }
}
public bool PreferredMember
{
get { return m_PreferredMember; }
set { m_PreferredMember = value; }
}
public PurchaseOrder Order
{
get { return m_Order; }
set { m_Order = value; }
}
}
}
Click here for a text-only version of this listing. Listing 2: The Purchase Order Domain Entity.
using System;
using System.Text;
namespace Acme.BusinessEntities
{
/// <summary>
/// Encapsulates elements used to describe a purchase order.
/// </summary>
public class PurchaseOrder
{
private string m_PurchaseOrderId;
private int m_TotalItems;
private decimal m_TotalPurchaseAmount;
private float m_DiscountPercentage;
private decimal m_ShippingCost;
private decimal m_TotalIncludingShipping;
public string PurchaseOrderId
{
get { return m_PurchaseOrderId; }
set { m_PurchaseOrderId = value; }
}
public int TotalItems
{
get { return m_TotalItems; }
set { m_TotalItems = value; }
}
public decimal TotalPurchaseAmount
{
get { return m_TotalPurchaseAmount; }
set { m_TotalPurchaseAmount = value; }
}
public float DiscountPercentage
{
get { return m_DiscountPercentage; }
set { m_DiscountPercentage = value; }
}
public decimal ShippingCost
{
get { return m_ShippingCost; }
set { m_ShippingCost = value; }
}
public decimal TotalIncludingShipping
{
get { return m_TotalIncludingShipping; }
set { m_TotalIncludingShipping = value; }
}
}
}
Click here for a text-only version of this listing. Listing 3: The PurchaseServiceTest Unit Test
Class.
using System;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Acme.BusinessEntities;
using Acme.RetailOperations;
namespace Acme.RetailOperations.Tests
{
[TestClass]
public class PurhaseService
{
public PurhaseService()
{
//
// TODO: Add constructor logic here
//
}
private TestContext testContextInstance;
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
[TestMethod]
public void ExecCustomerCheckOutDiscAmtShouldBeTenPercent()
{
Customer customer = new Customer();
customer.FirstName = "Robert";
customer.LastName = "Deniro";
customer.PreferredMember = true;
PurchaseOrder order = new PurchaseOrder();
order.DiscountPercentage = 0f;
customer.Order = order;
PurchaseService service = new PurchaseService();
service.CustomerCheckout(customer);
Assert.IsTrue(customer.Order.DiscountPercentage == .10f, "Expected .10 but was {0}",cus
tomer.Order.DiscountPercentage);
}
}
}
Click here for a text-only version of this listing. Listing 4: The PurchaseService Application
Layer.
using System;
using System.Text;
using Acme.BusinessEntities;
using Microsoft.RuleEngine;
namespace Acme.RetailOperations
{
/// <summary>
/// Provides purchase ordering functionality and integrates with BRE.
/// </summary>
public class PurchaseService
{
public void CustomerCheckout(Customer customer)
{
object[] facts = new object[2];
PurchaseOrder order = customer.Order;
// some logic
// Determine any discounts
Policy policy = new Policy("Customer Discounts Policy");
policy.Execute(facts);
customer.Order = order;
// some additional logic
}
}
}
Click here for a text-only version of this listing. Listing 5: The CustomerFactCreator Class.
using System;
using System.Text;
using Microsoft.RuleEngine;
namespace Acme.BusinessEntities
{
/// <summary>
/// Implements the IFactCreator interface for providing .NET types to the BRE for testing purpo
ses.
/// </summary>
public class CustomerFactCreator : IFactCreator
{
#region IFactCreator Members
public object[] CreateFacts(RuleSetInfo ruleSetInfo)
{
object[] facts = new object[1];
Customer customer = new Customer();
customer.FirstName = "Robert";
customer.LastName = "Deniro";
customer.PreferredMember = true;
PurchaseOrder order = new PurchaseOrder();
order.DiscountPercentage = 0f;
customer.Order = order;
facts[0] = customer;
return facts;