Dr. Paul
Dorsey
Dulcian,
Inc.
Business rules-based systems are the next generation of how database systems will be designed. There is now ample evidence to support this assertion. Emerging interest in business rules, whole business rules tracks at IT conferences, in combination with numerous vendors jumping on the business rules bandwagon indicate a growing recognition that even if the right solution has not yet been found, it is the right direction in which to proceed.
The last major shift in system design thinking was the change from first generation databases based on the IMS/IDMS environment to relational databases. Systems development had grown increasingly cumbersome. Modifications to systems were clumsy and expensive. Managing development and maintenance of these systems over time was a nightmare. The rule of thumb in such systems was that any ad hoc information request (special purpose report) took 10-20 business days to deliver.
Relational databases drastically improved this environment. Using relational databases, we were able to more or less nicely manage the data side of our systems. We still have large, complex and cumbersome systems but the data side is under control. However, the process side of these systems is still out of control. We are building programs not dramatically different from those of the early days of computers. Although we use 4th generation languages and powerful techniques for interacting with the database that have drastically improved efficiency, for complex business processes, the current method for building systems is largely unchanged.
There have been some attempts to try to improve this process. The entire Oracle Designer product had some success in managing the simple applications needed to support a large database. Using Designer, it is possible to specify and generate simple applications. However, I believe that Designer generation has ultimately failed. It does not work well for large, complex business events and is not well suited to the application of modern generic database modeling techniques. (For more details see my article “The Case Against Designer Generation”)
The simple-minded, version-one systems that we deploy become even more complex over time. Users want sophisticated security, complex workflow, seamlessly integrated manual and automatic processing. These are all features that database-centric systems are not particularly good at handling. Over time, these systems are collapsing under their own weight. Twenty years after the first relational database systems, our industry project failure rate is still about 70%. There are many reasons for this failure. It is not my assertion that adoption of a business-rule approach is the magic bullet that will solve all of our problems. However, it does solve one of the critical problems, namely coping with large and complex business processes.
By business rule-based systems, we mean creating an additional layer of abstraction in the system design. Rather than writing code, business rules are specified in a specialized repository.
Depending upon how the business rule solution is implemented, it may have no advantages over traditional systems. One of my first arguments with Bonnie O’Neil about business rules when she was working with Ron Ross (one of the gurus of business rules grammars) was about the usefulness of creating a business rule grammar. My argument against the approach was that we already had a business rule grammar, namely PL/SQL.
If you want to precisely describe exactly how your data needs to be processed, PL/SQL is the right language to support this requirement. We can articulate business rules using 3rd generation languages and have been doing so for years. PL/SQL or any other 3rd generation language is our business rule grammar.
If we have been using PL/SQL for all of these years, why do we need another language?
From a businessperson’s perspective, programming languages are unreadable, unmanageable drivel that is completely out of synch with the logic of the business events that it is trying to specify. However, anything that tries to replace PL/SQL or any other programming language must be equally sophisticated. With respect to some structure for representing process business rules, we need to create a new programming language.
Great! Just what this industry needs – another programming language.
The dilemma is that we need a new programming language but we do not want one. Part of the solution is to understand that “not all business rules are created equal.” If we can identify classes of business rules that can be easily specified using a particular mechanism, we can begin chipping away at the problem. Some business rules can be easily represented and we can write program code for the rest.
One could argue that this is what has been done all along. The venerable ERD is, itself, a mechanism for specifying business rules. It only easily represents structural business rules and is not at all suited for representing process-related business rules. For a reasonably large subset of structural business rules, ERD’s work fairly well.
The Oracle Designer Function Hierarchy and application generation allow for the representation and implementation of relatively simple business events. The business events that Designer can generate are largely single-step or a small number of multi-step business events. As long as you stick to the types of business events that Designer generation was designed to support, it is a useful tool.
Where we have failed as an industry is in creating a good solution to support complex process flow-related business events. In particular, Oracle has a long way to go in this arena. The Process Modeller within Designer seems to be suffering from inattention. If the traffic on the ODTUG list is representative, the Process Modeller has been dismissed as a nice drawing tool akin to Visio. Oracle’s Workflow product is little more than a fancy document router with little ability to specify a significant portion of the process-related business rules. CDM RuleFrame appears to take a generalized rule grammar approach but it is unclear to me how this will solve the process rule problem either.
There is still no one “right” business rule solution yet. At Dulcian, we have been using a business rule-based approach for several years now. We believe that by combining several different technologies, both the structural and process-related business rules can be easily and successfully implemented in the systems we build.
We use a multi repository method of approaching business rules based upon two mature, well-formulated and understood strategies for articulating them:
We do not assert that these two technologies will allow us to store and implement 100% of the business rules of any system. However, we have found that using data models in combination with state transition engines, we can support 90-95% of the business rules in a given system in these very easy to maintain repositories. This leaves a much smaller percentage of rules to store in a general grammar or in code.
Business rules may be divided into two categories:
A) Structural business rules: Largely state and time independent and may include everything from “Vice Presidents report to Presidents” to “Employees work in Departments.”
B) Process business rules: workflow, state dependent rules
A structural rule is one that is defined on the data structure independent of process. Rules indicating the types of information to be stored and how those information elements interrelate are structural. All information traditionally stored in a relational ERD is structural. An ERD lists the information groupings in the database (entities), the individual information elements (attributes) and (to a limited extent) how the information elements are related (relationships). This is a very limited “grammar” for business rules, but clearly is a type of business rule repository.
There are, of course, structural rules that are not easy to represent in an ERD. Even simple rules involving the relationship between 2 attributes usually cannot be represented in an ERD. For example, take the standard constraint that a starting date must precede and ending date. There is no way to store such information in a traditional ERD.
A process rule, on the other hand, relates to process or workflow related information. The rules associated with declaring the approval process for an invoice are clearly process rules.
Let me point out that this division of business rules into structural and process rules is artificial. Any business rule can be articulated as either a structural rule or a process rule. This is purely a taxonomy of convenience. There are rules that are more easily represented as structural rules and there are rules that are more easily as process rules. The goal is to represent all the rules in such a way that the cost of development is minimized.
To illustrate: consider the following 2 rules, one naturally structural, one naturally process related. As a structural rule, consider a trivial 1-entity data model of an employee as shown below:

There can be no clearer structural rule, yet even this rule could be represented using a process related business rule repository. Consider, the structure of an employee record is only relevant when inserting or updating an employee. If we placed rule checks on the operations that insert or update employees, then the employee’s structure could be controlled indirectly by controlling the process that manipulate employees. This would give us the ability to enforce the structure of the employee through its processes.
Similarly, consider any process flow. All process rules can be articulated using conditional logic associated with data fields. Even a complex state transition rule flow can be represented using data based rules. For example: “If the status of the order is “OPEN” and the current date is greater than 90 days past the day the order was created, then set the status of the order to “CANCELED””. I suppose that you could insist on calling this rule a “process” rule because of the setting of the status, but I believe that just a good a case could be made for calling this a structural rule. We are simply declaring a complex data rule that governs the automatic setting of an attribute based on the value of some other attributes.
If we control any business event that impacts a particular data structure by enforcing it in such a way that the structural rule is not violated, then we have effectively made our structural business rule into a process. Conversely, for business events that have an attribute called “State,” all process-related rules can be articulated at “If the value of the state attribute is ‘x’, then field ‘y’ must not be null.” Therefore, we can also represent any process business rule as a complex structural rule.
Both because of its status as an emerging standard and its ability to store more complex rules than ERDs, we have chosen to use UML class diagrams for our core structural information. Anything that can be represented in an ERD can be done in UML with the additional advantage of actually reflecting inheritance relationships in UML that are not possible to represent in ERDs.
In total there will be five possible places to store business rules in the system:
Therefore, the business rule environment is as follows:

Of the rules that are most easily represented as structural, most will be placed in UML diagrams. The rest will go into OCL. Of the process rules, most go into the State Transition Engine and the remaining ones are created as functions or procedures.
The question of whether something is a structural or process rule is a matter of choice. There is no effective algorithm for determination. Most things represented in an ERD are usually structural. The approval process for a purchase order is clearly process-related. Even so (as already mentioned), it is still possible to represent any structural rule as a process rule and vice versa.
Even within the sub-areas of structural or process rules (Triggers, Domains and Functions & Procedures), there is no clear way to decide where the business rule should reside. On the structural side, not all business rules can be articulated using a UML class diagram. However, any business rule articulated in a UML diagram can be articulated using code.
On the process side, it is even more complex. There is no obvious resolution to the question of where the business rule should be placed. The State Transition Engine is clearly a limited programming language. Anything that can be coded in the engine can also be coded as functions and procedures. Taken to its logical conclusion, this would mean that there would be no automatic states and each manual state could have a single procedural call as it makes the transition to the next manual state. This mechanism could execute all of our process logic. At the other extreme, you could supply nothing but very elementary functions and procedures that would allow interaction with other objects in the database. Virtually all of the program logic would then be stored in the State Transition Engine.
We still have not answered the question of where to put all of the business rules. If the business rule can be stored in any one of the four repositories, how can we make a determination about which is best? There is only one deciding factor: cost. The ultimate goal in any systems project is always to minimize the overall cost of the system over time. In our limited experience with this type of structure, we propose the following guidelines.
Everything that can go into the UML repository should be placed there. However, this statement must be tempered by possible complex specializations created to avoid a process-related rule or complex constraint represented in code. This guideline should not be adopted dogmatically. Thus far, we have not encountered any structural rules that could be represented in UML that could have been better represented in one of the other repositories.
If there is a non-state dependent business rule not easily represented using a UML class diagram, it should be articulated using code. For example, “start date must be less than end date” will clearly be represented using code. Our experience with class triggers is limited, but in performing earlier constraint-based grammar work, our conclusion is that if the rule is state-independent and can’t be represented in UML, it should be represented in code.
In the other similar system we built, one of the main people working on it was not a PL/SQL programmer. Therefore, all of the program logic was placed into the State Transition Engine and only rudimentary update procedures and functions were used. At the time I worried that this did not seem to be the most efficient model. Complex routines might be better represented in traditional code rather than in the State Transition Engine. Performance was also an area of concern. In this particular case, the way that the state transition engine was implemented did not create any performance degradation. The generated code is clean and consistent, leading to acceptable performance.
There may be an almost overwhelming temptation for skilled developers to write PL/SQL code and not use the engine until the user interface is better. This would be a mistake. Because of the way that process-related rules are articulated, it is easier to work with, debug and maintain. Although it is not possible that 100% of all process can be stored in the State Transition Engine (rather than in PL/SQL code), it is useful to place as many process rules there as possible and only use PL/SQL for functionality reasons or when the engine proves to have inadequate performance.
“If all else fails, write code.” If possible, think of functions and procedures as extending the capability of the State Transition Engine and providing functionality that would not otherwise be possible rather than writing code in place of building process flows.
UML is only somewhat more robust than ERDs with respect to representing business rules. However, UML is extendable. Once we had decided to support our own business rule repository, we were no longer limited by what UML had to offer. We created several extensions to support our repository structure:
There are two types of history: simple and complex.
Specified by applying the keyword “HIST” or “History” to the class. Note that history can also be applied to an association, meaning that it is being applied to the automatically generated association class. With simple history, two additional attributes are automatically added: StartDate and EndDate. The PK of the object does not change.
As mentioned, simple history may also be applied to an association. This does not necessitate or imply the creation of an association class. As with objects, StartDate and EndDate are applied to the associations.
StartDate and EndDate are added as attributes to the class.
NOTE: StartDate and EndDate need not be specified as attributes in the UML diagrams. The only reason to include these would be to change the multiplicity or domain of the StartDate and EndDate. By default, start dates and end dates allow any valid date except where they violate the history constraints as described below. Both are optional.
Neither the start date nor the end date may be after the current system date. If you want objects with future effective dates, you should add additional attributes to the class for this purpose. The History keyword has a very precise meaning and does not support this functionality.
If StartDate and EndDate are both not null, StartDate must be less than EndDate. Records may exist without Start Date when the start date is indeterminate. This is often the case for data migrations. However, you cannot have a logically deleted record without an end date since deleted records are detected by a non-null end date.
NOTE: Record status is not additionally maintained as part of history. If desired, record status should be added and manipulated as another attribute on the class.
By placing a “History” keyword on a class, when that class is brought into the repository, it is expected that a start date and end date will automatically be added to the class. If the start date or end date multiplicity or domains have been overridden by the diagram, these overrides should be passed to the repository.
When you create an object with history, a start date of SYS_DT is assigned to the start date attribute by default. StartDate is an optional parameter in the Create Object command and can be overridden by passing a start date parameter at object creation.
StartDate behaves like any other attribute and can be modified or made null using a Set Attribute command.
Applying a keyword of “History” to a class does not affect the behavior of its primary key. This is equivalent to setting an active flag on a relational database record. The record still exists. If an Employee with an EmpID as a primary key exists and history is associated with the Employee class, when the Employee is deleted, you cannot insert a new employee with the same ID.
To remove the Employee record from the database, use the overloaded DELETE-OBJECT function. You can either pass the delete date or the character string “remove” in the position of the optional parameter. If you pass “remove,” the record will be removed from the database.
Complex history involves the tracking of history on the record and allows duplicate primary key values in the class.
Primary key history behaves in a similar way to regular history since start date and end date can be added. The commands used are the same and behave in the same way with the following exceptions:
Org {Hist_PK} OrgID {PK}
The following are examples of successful and unsuccessful
insertions to an organization class.
|
|
Original |
New |
|
|
|
|
Object |
Object |
|
|
|
OrgID |
100 |
100 |
|
|
|
StartDate |
1/Jan/2000 |
1/Jan/2001 |
Succeed |
|
|
EndDate |
1/Jan/2001 |
|
|
|
|
|
|
|
|
|
|
OrgID |
100 |
100 |
|
|
|
StartDate |
Null |
1/Jan/2001 |
Succeed |
|
|
EndDate |
1/Jan/2001 |
|
|
|
|
|
|
|
|
|
|
OrgID |
100 |
100 |
|
|
|
StartDate |
1/Jan/2000 |
1/Jan/2001 |
Fail |
|
|
EndDate |
Null |
Null |
|
|
|
|
|
|
|
|
|
OrgID |
100 |
100 |
|
|
|
StartDate |
1/Jan/2000 |
1/Feb/2000 |
Fail |
Not implemented |
|
EndDate |
1/Jan/2001 |
Null |
|
|
Effectively, we are relaxing the PK constraint so that the class may have duplicate primary keys as long as the StartDate and EndDate do not overlap. This constraint must be checked every time any primary key columns are changed, when the StartDate or EndDate attributes are set and whenever an object is created.
The StartDate and EndDate are implemented in the PARTY_VAL table. The Activ_yn is in the object tables and as a column in the PARTY_VAL table.
You may also apply a “history” keyword to an association. This allows for logical deletion of associations. The Create Association and Delete Association commands behave the same as the Create Object and Delete Object commands on classes with history. You can pass a date on either creation or deletion of an association. You can pass a date or pass the keyword “remove” to actually remove the association from the database.
Associations with not null end dates are automatically ignored in cardinality checks by the engine.
History has an impact on the cardinality of rule associations. In particular, sometimes you want the association to be considered part of the object and the history class. At other times, you do not. In Figure 3 and the example below, there are sales attached to customers and customers are placed together in customer groups with no more than ten customers in each group.

Figure 3: History on associations example
If the customer is no longer in business and needs to be deleted from the system, in the case of a sale, we do not want the deletion of the customer to orphan the sales records. Neither do we want to inactivate the association of the sale record since that would allow the sale objects to be attached to an additional customer.
However, in the customer group, the opposite situation exists. When the individual customer is inactivated or deleted, their positions in the customer group should be available to another customer. Sometimes the deletion of the object should also invalidate or delete its associations but not in every case.
The way that the engine works, associations are stored independently from the objects that they attach. Cardinality rules are validated by counting valid records in the association table. Therefore, in the implementation of history, when a command is received to delete a history object, this triggers no validation of any cardinality rules since the engine cannot determine whether cardinality restrictions should or should not be observed in any given situation. When deleting history objects, the applications must determine (on a case by case basis) whether a particular association should be deleted, invalidated or ignored. The cardinality rules will be enforced when any attempt is made to invalidate or delete an existing association.
As mentioned above, each class in the UML data model is physically instantiated as a table. Each attribute in the class becomes a column. Foreign key relationships are handled using a reference to the master table OID rather than using the logical primary key.
Specialization classes include attributes along the generalization path. For example, in the EMP class, a Last Name and First Name column would be included if EMP is a specialization of PERSON. The UML engine is smart enough to handle an Insert or Update into EMP ASSOCIATED VIEW by inserting, updating or attaching to the appropriate person record.
We use keywords attached to UML objects to specify various physical column and class names. For example, to express a many-to-many relationship between two classes, you will need an association table between the two classes. If designers do not want to draw an association class, they can simply attach a keyword to declare what the name of the association table will be. Foreign key columns are named using the PARENT CLASS NAME_OID, but can be overridden via a keyword on the association.
Many-to-many associations between abstract classes become complex because an association table between any of the underlying subclasses may be needed as shown in Figure 4.

Figure 4: Many-to-many associations between abstract classes
In this case, the designer may want to have as many as twelve association classes because you will not only need association classes between all of the subclasses, but also the superclasses (an EMP-DEPT association class). How will these tables be named? As a keyword on the many-to-many association, the class pairings to be physically instantiated as tables are specified along with their names. It is beyond the scope of this paper to describe all of the notational nuances that we have used to extend UML.
The State Transition Engine (STE) defines an activity-based workflow for a business process. It is key to note that the states in the STE are not defined based upon static objects (Parties, Products, etc.) but, instead, on business events such as Sales, Invoices, Hiring Employees, Adding Products, Modifying Existing Products, etc.
Most, if not all modifications to static data structures will be made through business events or DOCS. Even then, the DOCS do not ever directly interface with the core physical structures. Instead, the DOCS make data modification requests to the UML engine, which checks the validity of these requests. The UML engine then performs the DML operations.
It is possible to have an application independently make a request to the UML engine for modification to a code structure without generating a document. However, such a strategy will necessitate that any workflow associated with that operation must be hard coded into the application with only a minimal audit trail. For this reason, we anticipate that most applications, rather than making modifications to the underlying data structure, will instead make requests to the STE engine. Exceptions to this would be cases where a complex workflow and audit trail are not required such as the maintenance of geographic regions.
In all but a handful of cases, insertion and modification of Parties will be maintained through generated documents. These documents can be created using one of a number of mechanisms:
The creation of workflows is quite an art. Typically, most analysts accustomed to building business process workflows think in terms of creating a workflow for analysis purposes in order to communicate how the business events are processed back to users. This is not the case in this system. The process flows here are actual program code. We have invented a focused, graphically based program language called State Transition Language (STL) to perform the specific function of articulating complex business workflows.
If we are merely creating program logic, the question arises: What are the advantages of STL over any traditional programming language such as C++, PL/SQL or Java? First, STL itself is limited. The developers are confined to creating assignment statements within states. There is nothing to prevent the creation of tasks that are whole blocks of code. There may be cases where this logic is needed. In general, not having an central structures, blocks or loops existing within a state keeps the states small and the generated code will be well managed and easy to debug.
Second, because STL is really a program specification language, the actual program executed is generated from the STE repository. This independence of the program specification from the program provides unique tuning capabilities. It is easy to think that code written using this engine would run slower than that created in a more traditional way. Theoretically, this is correct. An expert programmer could build a more efficient program than what is generated. Due to the low overhead of the STL-generated code, the optimal program would not be significantly faster than an STL-generated program. In practice, the opposite is true. Because of the rigor of the STL process and generated code, there are fewer places where a programmer can go astray. Coupled with the improved debugging and tuning environment, using the STL is a better option. For very complex routines where code must be perfectly optimized, it is possible to build large functions or procedures that are called by STL tasks. This enables you to have the best of both worlds:
• Use STL specs for clarity and manageability of code.
• Where high performance is required, routines can be built outside of the STE with all of the performance benefits of traditional code.
One of the most difficult decisions to make with regard to the State Transition Engine is determining what exactly is a process flow. The following analogy is useful in understanding how the process flows work.
“Imagine a room full of workers, each of whom is either an executive or a clerk. All of the workers in the room process one type of business transaction, namely a sale. Each executive and each clerk sit at a desk with an inbox. Each executive and clerk has very precise instructions about what to do when a piece of paper is placed in his/her inbox.
Executives (equivalent to manual states) select a paper from their inboxes and are given access to one or more pieces of information on the paper to View but Not Edit or View and Edit. Then a judgment must be made about where the paper goes next after processing is completed. The paper then moves on to the next inbox.
As soon as a paper is placed in their inboxes, Clerks (equivalent to automatic states) immediately perform a series of specified tasks. No judgment is required to perform these tasks. Based upon hard coded rules, the paper is passed to the next inbox. This process continues until either an executive (by choice) or another clerk (according to precise rules) places the paper into the completed basket for the Sales room.”
A business event may be fairly complex. It can pass through multiple individuals’ hands. When going from one individual to another, it can pass through a complex automatic workflow for any part of the process capable of precise articulation.
Each document starts in a CREATE state. There are many different things that can be done with any given document. For example, a Change of Address document may require the information about who is changing the document, old address, new address and any other relevant information. To complete this processing some rule(s) is applied.
This is not necessarily a linear process. At each point, there are some decisions made.
Any document can go through a combination of manual and automatic states. In a manual state, the user is able to view/edit/update the document. In an automatic state, a document will move through a series of states automatically without any user intervention. A sample diagram is shown below.

Figure 1: Manual State Workflow
When a document is initially set to a manual state, one of many things may happen:
• Document may just sit and wait with some type of expiration timer
• ON SET tasks may be initiated automatically
• BEFORE OPEN tasks may be executed as soon as the document is opened (Ex. logging who is opening the document)
• User selects from one or more alternatives (outcomes) as a transition to the next state. This may be determined by the application of a rule to the outcome. If the rule succeeds, the document moves one way; if it fails, the document will be handled differently.
When a document enters an automatic state, the rule engine checks the applicable rules and applies the tasks associated with those rules automatically. Ex. “IF Outcome A…..THEN…, IF Outcome B….THEN…” A sample data model is shown in Figure 2.

It is tempting to define a business process as only a small piece of a logical workflow. For example, in hiring an employee, you might think that the initial interview, approval and actual hiring are all separate business processes with associated workflows. From the STL perspective, it is better (i.e. less work) to combine the three steps into a single state transition process.
Continuing the analogy of a piece of paper passed from inbox to inbox, for hiring an employee, a manager would fill out the initial approval of a candidate which would travel from person to person. This should probably be represented as a single business process since there is some complexity associated with having a process pick up on an earlier associated process and continue it. For example, once the interview is complete, an approval must be given. These are really two parts of a single process separated by time. A user would simply need to open the document in the approval state and operate on it accordingly. If the interview/approval is treated as two separate processes, it will be necessary to create a blank approval document, find the relevant approval document and copy the appropriate information. This is a much more complex process.
Process related business rules are handled using the state transition engine in conjunction with additional functions and procedures. This engine defines process flows against business events and not against data objects. For example, in a retail system, a workflow would not be defined as a type or computer or software. Instead, this type of workflow should be defined as a business event called “Computer Sale.”
This change in thinking about state transition engines using business events enables us to build systems more consistent with the way that organizations think about their business. For example, business people do not think about workflow associated with an asset, but do think about workflow in terms of acquisition or retirement of an asset. For example, using Griffin, the retirement of an employee and not the employee him/herself has a defined workflow.
This is a more natural approach to building business-related systems. However, if the Griffin system user chooses to define workflows on types of objects, they can define a default business event (one for each type of object) and the state transition engine can be used for core data objects.
A state in our state transition engine is larger than traditional engines since it is modeled after the way business works. Our state transition engine simulates the work done by an individual in a manual document-processing environment. “Docs” (business events) are placed in the Inbox. A worker collects them, performs one or more tasks and makes a decision about whose Inbox the job should go to next. Tasks can be performed and triggered by the Doc State itself as well as while in transit to the next state. This level of complexity in the state transition engine allows us to greatly decrease the required number of states, thus simplifying the process of articulating the business rules for the system.
When performing tasks such as “Find out if a customer is a preferred customer” or executing a database procedure that updates one or more records in the database in the State Transition Engine, additional information is necessary. In these cases, we extend the state transition engine grammar to include the possibility of calls to functions or procedures where necessary.
This article discusses the importance of the business rule approach to system design and provides some details about how we are trying to solve the problem of supporting both structural and process-related business rules. We are confident that we are on the right track.
A generalized business rule grammar does not make sense. What does make sense is trying to classify the business rules and support them in ways that are easily managed and maintainable over time. Technically, we will evolve the solution by adding functionality and improving performance. However, there is still a whole area that has not been addressed. At last year’s ODTUG Business Rules Symposium, I created the following taxonomy:
We have gotten a large portion of parts 2 and 3 solved. We have created a fully functional application to handle the representation and implementation of the business rules. Now that we have the right technical approach, the question remains: How do we work with users to articulate the business rules, or, even better, enable users themselves to specify their own business rules in a way that we can use? Even though non-technical users can specify the process flows associated with their own business events, what they generate can be vastly improved upon by a skilled designer. There is still a lot of work to do.