◷ Reading Time: 5 minutes
A rule application is an application that requires business rules of some sort for execution. This application can be any type (e.g., web application, service, WinForms, etc.) and can consume any type of architecture (e.g., MicroService, multi-layered architecture, etc.).
To ensure your application gets the most out of a rule-based design, you would need to follow certain guidelines for designing your rules and the application. Utilizing these best practices ensures:
- Simpler and more consistent rule authoring
- Easier update of logic (i.e., rules, decision tables, flows, etc.)
- More reusable building blocks in modeling
These are the patterns.
This pattern recommends using a layer of indirection between your business logic layer and the application domain layer. Your existing application layer might be something similar to the picture shown below:
This is a typical layering, and what happens is that your rules directly communicate with your domain layer. The domain layer is the domain model of your application. With the application of this pattern, the proposed solution would be similar to the architecture shown below:
Fact layer is an abstraction layer that simplifies rule modeling and encapsulates the complexity of the domain based on different rule scenarios. In this design approach, your rules will not use the domain layer’s objects. Instead, an indirection layer sits between rules and domain layers. Your rules will be using Facts to interact with the information and data provided by your domain model.
There are many benefits, mostly because of the “Single responsibility principle” approach of the facts layer:
- Isolates the domain model that is involved as a result of the behavior of the rules
- Simplifies access of the information in the rules
In terms of development and maintenance, the only disadvantage would be the addition of one more layer which requires care.
When you are building up your rules, at some stage they will be bound to Runtime objects in the execution using Expressions. These expressions can be based on your application and/or domain objects – or even better, based on facts.
This is typically considered a bad practice and will result in different sets of complex expressions scattered all over different places in your business logic models (i.e., Decision tables, trees, flows, etc.)
Rather than having expressions scattered everywhere, you should create building blocks using the following:
- Boxed expressions
- Business glossary
Using these instead:
There are many benefits to doing that:
- These will encapsulate a complexity of expressions so that the rule author deals with straightforward rule entry rather than dealing with building expressions
- Gives rule author meaningful building blocks in their domain and language to build up rules
- Builds a portfolio of reusable building blocks that increases reusability
- Significantly enhances rule modeling and simplifies the understanding of rules logic
- It standardizes the approach to defining rules, so growing your rules-based application is safer and easier.
Builder patterns are used to create the expressions of business rules.
For example, in form validation, if you want to build the expressions and run the business as well, you can use this pattern. So the expressions are,
- IF Age < 18 THEN Show a message “Age should be at least 18 years”.
- IF Country is not Australia, THEN Show a message, ” Must be an Australian”.
This can be modeled as,
|Age||<||18||Age should be at least 18 years|
|Country||isnt||Australia||Must be an Australian|
|Score||<=||70||Score is not less than the minimum requirement|
|Valid License||is||false||Must have a valid license|
- The expressions are clearly visible to the users making it easier for them to understand, edit and maintain.
- If there is a long list of business rules that do not relate to each other, you can list the rules instead of creating a long decision table expanding horizontally.
- If there are complex expressions with multiple monads, it can reduce the readability when you add them as cell values.