Home > Candidate Patterns > Rule Layers

Rule Layers

How can business rules be organized based on functional commonality?


When placing rules into a single location (rules centralization), they can still be delivered by different projects and project teams without anyone governing how these rules are organized and structured. Rules normalization contributes to this pattern but does not categorize rules nor does it explicitly structure the rules into logical groups.


Apply rules normalization (context abstraction) and enhance this by further introducing logical layers of rules into the rules inventory. Each layer has a specific purpose to facilitate separation of concerns driven by normalization based on a common functional type. Introduce rule types to facilitate for agnostic and non-agnostic rules.


Categorize rules into groups with functional similarity. Create two or more rule layers logically organized into at minimum two (an agnostic and a non-agnostic) logical rules layers.

Assign rule types and assign each rule type to a specific rule layer.

This pattern distinguishes between at least three different rule types:

  • Utility Rules
  • Semantic rules
  • Task rules

Utility rules are agnostic rule definitions. Semantic rules are rules create to establish separation of concerns to create a set of meaningful rules in a semantic agnostic context. The purpose of these rules is still reusable and additionally they are used to create an indirect access layer to the utility rules layer. Process context or service context is typically not allowed into the semantic rules layer.

No direct access to the utility rules layer should happen in order to keep separation or concerns inside the rules definition. This part of the pattern is similar to the official endpoint layer. Consider it the official rules endpoint.

On top of these two layers, define a non-agnostic rules layer, named a task rule layer. This layer can be used to provide functional/process context to the underlying rule base. Task rules should also be concerned normalized assets. This means that task rules can be grouped into normalized groups with similar functional context. This could even trigger the definition of additional non-agnostic rules layers.


Rules are more easily understood and ultimately allow for a better understanding of the (distributed) system they are being used in.

This makes consequences of making changes to rules more easily understood.

Because centralized and normalized rules become layered, a performance bottleneck can be expected, which can affect the amount of required hardware resources.

The initial analysis and definition may cost additional effort.


Service Inventory, Service


Under Review


Roger Stoffers

Table: Profile summary for the Rule Layers pattern.


With the rules centralization pattern, rules are centralized into one physical location. When applying the rules normalization pattern, these rules can still be delivered by different projects and teams. This does not dictate how these rules are organized and structured inside a potential rules management system. Although rules normalization creates rules boundaries, no classification is applied beyond this, which results in a governance for the rules boundaries.

Consequently this can cause a situation where, because of different designs and design standards, rules are still cluttered because of -to service designers hidden- interdependencies between rules. Consequently rule changes can still trigger effects into unexpected locations, because changes can indirectly cascade into places not foreseen.

This affects the service loose coupling in a negative way. Making a change in a rule for one service may have undesirable effects in other services.


Figure 1 - Rules are normalized but used and reused by various services in different contexts which creates (indirect) coupling between services and services depending on rules. This can cause the need for elaborate investigations into the service inventory which can be cumbersome.


This pattern recognizes that rules are categorized into rule types and layered using a logical grouping. It distinguishes between two distinctly different types of rules, organized into layers supporting the separation of concerns facilitated by rules normalization:

  • agnostic rules layer
  • non agnostic rules layer

By abstracting rules with context into the non-agnostic rules layer, the remaining agnostic rules layer should only have rules that are truly agnostic and can support multiple contexts. This is what gives rules reuse potential.

Agnostic rules

Rules have reuse potential if they:

  • provide support not specific to one specific business process
  • can be applied for more than one purpose

The former characteristic classifies the rule as agnostic; the latter gives it reuse potential.

In the context of this pattern, two agnostic rules layers can be identified to increase separation of concerns, directly in support of the service loose coupling principle:

  • utility rules definition
  • semantic rules definition

The utility rules (raw base rule definition) holds definitions for rules and should not be accessed by rule consumers directly to support loose coupling inside the centralized sets of rules.

The semantic rules hold semantic definitions for rules, which gives a meaningful context to an underlying rule, whilst keeping the rules multi-purpose(*).

Sometimes it's not possible to distinguish between utility and semantic rules, simply because the rule name sufficiently describes its purpose. In that situation, assign the rule to the semantic rules layer.

(*) Risk of introducing non-agnostic context exists. Functional context should be expressed in an agnostic way to create reuse potential. The purpose of this layer is to create a layer of indirect access to the underlying rules definitions. Any process or application specific context should be defined in a non-agnostic rules layer

Non agnostic rules

Non-agnostic rules are considered to have limited reuse potential as they

  • are specific to one or a limited set of business processes
  • can only be applied in functional context of a specific service consumer or process.

Non-agnostic rules can be, because they have process-functional context, considered task rules; they are intended to help fulfill a specific task and are therefore considered less reusable.

Non agnostic rules may allow for overlapping boundaries with care.


Figure 2 - Rules defined in the service inventory are, after being normalized, abstracted into logical layers of rules.

As indicated, a distinct difference exists between task rules (non-agnostic) and semantic rules (agnostic): While task rules are tailored to operate in one specific context, semantic rules, although giving a certain level of context, only give context (meaning) to the rule. Another way of explaining is that they do not pertain to the environment in which they are being executed but to the underlying rule they are being applied on.


The actual application of this pattern can best be illustrated by using examples. Please note that the examples do not follow any official notation standard or language.

Create a utility rule set.

Examples of utility rules are:

  • adultAge := 18 yrs;
  • validPaymentTypes := ENUM("DirectDebit", "CreditCard")
  • validDayIDs := ENUM("Su", "Mo", "Tu", "We", "Th", "Fr", "Sa")
  • validPaymentTypes := ENUM("DirectDebit", "CreditCard")
  • service number plan range is = (080*)
  • geographically bound number plan = (01*, 02*, 03*, 04*, 05*, 07*)
  • mobile number range = (06*)
  • internet service provider number range = (066*, 067*)
  • semaphone number range = (068*, 069*)

Create a semantic rule set. A semantic rules definition gives meaning to the rule but still remains multi-purpose.

  • isAdult := (age >= adultAge)
  • isFutureDate := (date > sysdate)
  • isPastDate := (date < sysdate)
  • isTodayDate := (date == sysdate)
  • isValidPaymentType := (paymentType IN validPaymentTypes)
  • isValidDay := (dayValue IN validDayIDs)
  • DutchPostCodeFormat=(RegExp:"/d{4}/w{2}")
  • PSTN whitelist numbers = resourceValue IN (Geographically bound number plans)
  • PSTN blacklist numbers = resourceValue IN (service, mobile, internet, semaphone)
  • MSISDN whitelist numbers = resourceValue IN (mobile)

Create a task rule set. A task rule definition is always executed in a certain context and should always be used in that context only.

  • validSaleProcessActivities := (IF processValue=="Sale" THEN activityNameValue IN ("a", "b", "c") )
  • validCheckoutProcessActivities := (IF processValue=="Checkout" THEN activityNameValue IN ("b", "c", "z")
  • nextProcessActivity := decision table: (IF processValue=="Sale", lastActivityValue=="x", allValidationsPassed, AllActivityLogicSuccessfullyExecuted THEN "y")
  • validLicenseExpiryDate := (isTodayDate OR isFutureDate)
  • saleProcessAllowedFixedLineNumberRange := {PSTN Whitelist} \ {PSTN Blacklist}
  • saleProcessAllowedMobileNumberRange := {MSISDN Whitelist} \ {PSTN whitelist} \ {PSTN blacklist}

A rule consumer can either access the task rules or semantic rules, but should not access the utility rules directly.


Figure 3 - Once rules are normalized and layered, direct access to the utility rules is disallowed to avoid consumer to implementation coupling and additionally supports separation of concerns to avoid inter-service coupling due to unintended sharing of rules in a different context. Various consumers can have different ways of accessing the same underlying rules, but only if deliberately designed to access these in a well-defined context.


Because of the separation of concerns (functional context abstraction) into specific layers, more up-front analysis and modeling is expected.

Due to more (layers of) rules and inherently more expressions/evaluations being executed at runtime, system performance demands and system resource demands may increase.

Redundant implementation may help overcome any availability or predictability issues caused by the increased resource demands.

Because rules of similar context and purpose are grouped into logical layers, the system of rules is more easily understood and consequence of change can be overseen more easily once the layered structure has been established.


Rule layers is a pattern similar to service layers being applied to Rules.

As more system resources are claimed, the autonomy of the services accessing the layered rules may be affected.


Figure 4 - Rule layers help increase service loose coupling at the cost of service autonomy. Service normalization is supported by further grouping rules of similar context into logical layers.

Note from the author:

The classification of the rule types mentioned is a proposal. Better names may exist and I encourage everyone to come up with better names, especially for the two agnostic rule layers introduced in this pattern.