Guide‎ > ‎

Logic Design Patterns

There are several key design patterns when utilizing logic. It is important that each team member be conversant in these.


Forward Chaining: constraining chained derivations

Probably the most common pattern is defining a constraint that requires a series dependent derivations to produce the data used in the constraint.  The most familiar example is Check Credit, where the Customer's balance is derived by a series of derivations over 3 Domain Objects.

Business Logic services enable you to access data from related Domain Objects:
  • Sum and Count rules enable Parent objects to aggregate related child data
Automatic adjustment processing occurs when child rows are changed in such a manner 
Automatic Cascade processing occurs when the parent row's reference data is changed

Counts for Existence Checks

The count derivation can produce a count of related child rows, optionally qualified by a condition.  In many cases, the objective is to know whether the count is 0 or non-zero - that is, are there any [qualified] children.   For example:
  • the No Empty Orders requirement is implemented by a countItems, which is then checked in a constraint

  • the Bill of Materials Explosion (see rules 1 and 2) requires identifying whether a Product is a kit - has any components

Replicate Junctions

You introduce Junction Objects for many-to-many relationships between 2 end-point objects.  It is often a requirement that an end-point object needs to sum/count an attribute from the other end-point.  Since sums/count operate on 1:n relationships - and not n:m relationships, you will need to replicated the summed attribute into the Junction.

The replicate can take two forms, depending on whether the sum should reflect changes in the summed attribute.  The Tutorial illustrates both, as discussed in the sub-sections below.

Do reflect summed changes into sum: use Parent Reference

The Bill of Materials Price Rollup example illustrates is a many to many relationship between Product objects, informally referred to as Kits and Components.  ProductBillofmaterials is the Junction Entity implementing the many to many relationship.  A Kit needs to sum its components price to determine its own price.  

Since the Business Requirement is that Component price changes be reflected in the Kit Price.  The Logicdoc illustrates that we define ProductBillofmaterials.value as kitNumberRequired * product.price. We can then sum this result into the Kit.

This Formula contains a Parent Reference to the product.price.  Formula parent references reflect changes, unlike @copy logic as shown in the next example.

Do not reflect summed changes into sum: use @ParentCopy

The Place Order example illustrates a many to many relationship between Purchaseorders and Products, where Lineitem is the Junction entity.  Purchaseorder.amountTotal is the sum(Lineitem.amount).   

Our business requirement is that we do not wish to change Purchaseorder amountTotals for subsequent Product price changes.  We therefore define Lineitem.amountTotal as an @Copy of Product.price.

Request Objects

The classic request pattern is to invoke behavior from the construction of Command Objects.   Such objects can be maintained in a list and used for undo, for example.

The same pattern can be used in data processing applications.  The request object is inserted, representing a transaction requesting some behavior such as a Credit Request, or an Employee raise.  Instead of code, you declare logic to implement the desired behavior.

Form Flow based on Derivation Results

It is a very common requirement to drive Form flow based on derivation results.  For example, you might define a Wizard for Document Processing, with tab sheets enabled/activated on the basis of whether restricted Products are ordered, or the customers credit history.  Derivations are excellent mechanisms to compute the data used to drive such conditional transitions.

Recall that derivations fire only when a transaction is saved.  We therefore recommend using the Read Pattern, as described below.

Direct Logic Invocation (without updates)

Business Logic executes in response to an insert, update or delete of a Domain Object.  ABL also provides support for Direct Logic Execution without first requiring an update.

Ready Pattern

Imagine an interactive transaction where the End User proceeds through a set of screens. When screen-1 is complete:

  • Business Logic derives various data
  • These derivations are then used by the Presentation Layer:
    • For display
    • For conditional processing (eg, a conditional transition, or to cause hiding of not-relevant portions of the screen)

Of course, it is highly undesirable to hold an open database transaction (and blocking locks) over screen transitions. Given that you need the Business Logic derivation results as noted above, this suggests that you should submit - and commit - changes at the completion of screen-1.

But this presents a problem: it might not be appropriate to "post" this incomplete transaction (e.g., adjust General Ledger, the Customer Balance, Product stock) until all the screens are complete.

We have all seen such an example in on-line shopping. We can fill our cart, and see how much things cost (a derivation), as we shop. It is only when we checkout that our account is charged.

The Best Practice approach is to:

  1. define a isReady attribute (e.g., in Purchaseorder)
  2. its value is false until the checkout screen, at which point it is set to true
  3. when defining rules, predicate the rules on isReady == true as in Place Order
    Derive Customer.balance as Sum (purchaseorders.amountUnPaid where isReady=true)
    This of course requires that you provide a Make Ready (aka "checkout") transaction to activate the remaining logic.

    Commit Time Logic: Constraints, Actions

    Be aware that logic processing occurs in two phases: logic phase (initial row processing), and commit phase (after all rows are processed).  Counts of inserted child rows are always 0 during the logic phase, so requirements such as No Empty Order (which depend on the count value) need to use Commit Constraints.

    Parameterized Formulas

    It is often necessary to enable Business Users to alter data used in formulas.  For example, you might apply a discountAmount to a Purchase Order.

    You can achieve this easily as follows:

    1 - Create a 1 row Domain Object (e.g., Parameters)

    Create a "scalar" Domain Object (e.g., Parameters), with attributes you want authorized Business Users to change, such as discountAmount.  Provide access to this object in your applications' user interface.

    2 - Provide getParameters() in superclass of Logic Classes

    Define your Logic Classes to extend LogicBase (see BusLogicIntro), where LogicBase implements the method to return the single Parameters object

    3 - Use LogicBase in formulas

    getParameters() can be used in formulas (just as Parent references), e.g., getParameters().getDiscountAmount()


    The following sections describe patterns implemented by the extension package provided with the product.  These are critically important, both for use (they are very common patterns), and as illustrations of how to provide logic extensions.


    The allocation pattern can be summarized as follows:

    Allocation Pattern

    Allocates a provider amount to designated recipients
    creating allocation objects (a Provider/Recipient Junction) for each such allocation. 

    Put differently, the system receives a quantity of things (money, goods), and allocates them to a set of recipients. Some examples:
    • Allocate a Payment to set of Purchase Orders
    Allocate a provider Payment.amount to designated recipient Purchase Orders
    creating allocation Payment Purchaseorder Allocation objects (a Provider/Recipient Junction) for each such allocation.

    • Allocate a Department Bonus to a set of Employees

    • Allocate an expenditure to a set of General Ledger accounts

    • Allocate a sum to a set of organizations (who, via chained allocations, allocate their allotment to designated General Ledger accounts)

    Business Logic supplies allocation as an extension.

    Insert From (copy)

    It is a very common requirement to copy one or more source rows to target rows.  A corollary requirement is that the created target rows are usually children of the source rows, and require proper initialization of their attributes.  The general concept is loosely analogous to the SQL Insert Into Select From command.
    • Auditing
    This is simply a copy of the current row, under the proper conditions.  We illustrate a common example in Salary Auditing.
    • Deep Copy
    It is a common requirement to "clone" a Business Object, meaning a "master" and its related objects.  For example, a customer might like to create a new order by copying an old one.

    • Bill of Materials explosion
    This is widely regarded as a particularly tough pattern.  We shall see it is, in fact, a variant of a deep copy, and can be solved with just a few rules.

    Click the title link for further information.

    Inclusion / Exclusion logic - Find Where (search collection)

    It is common for logic to require searching lists to verify whether or not objects are present, for example:
    • Inclusion - assure a row is included
    For example, an Employee might have 2 child collections of languages: spokenLanguage and translatesLanguage.  It is reasonable to ensure that each spoken language has a row for that user / language in spokenLanguage.
    • Exclusion - assure a row is excluded
    For example, in a Bill of Materials definition, it is desirable to ensure that a component is not also the containing part.

    We therefore provide a set of logic services for FindWhere, that enable you to search through a list to find rows that match a specified criteria.  You can search for the first row that matches, or the only row (which throws an exception if there are multiple matches).
    Document processing are business activities that involve filling out multiple forms.  Together, these forms might comprise an application, for example an insurance application.  Common characteristics of Document Processing include:
    1. Form Generation: questions on an initial "cover" document might engage logic to determine which detail forms are required.  For example, you might need to complete special forms if you are applying for insurance and engage in high-risk hobbies, to determine the actual risks you are undertaking.  Or, you might be required to complete special forms if you attempt to purchase controlled substances.

    2. Multiple Sessions: the Business User may need to do research / consulting to respond to all the questions.  Since this may require days, it is not practical to hold locks open, so there is typically a series of database transactions to complete a Document Processing activity, possibly engaging multiple users in a workflow.
    Business Logic can help in such cases.  You can handle Multiple Sessions by using the Ready Flag, described above.  Form Generation can be automated with Insert From logic as described in this Document Processing example.