Docs‎ > ‎API Creator‎ > ‎Specify your Business Rules‎ > ‎

Logic Patterns

Explore the key design patterns of reactive logic in the context of running examples, such as those provided in the reactive logic tutorial. They are also provided with Live API Creator, so you can experiment with real transactions, and study the logs, for example.

You can use the Table of contents as a checklist of the key design patterns.

Key Concept: Think Spreadsheet

API Creator provides an event model, wherein you can write JavaScript event handlers to handle table updates. Experienced programmers will understand them instantly.

The key to getting the value out of API Creator is to use events in conjunction with spreadsheet-like rules. We call the concept "Think Spreadsheet", and a good way to understand it is by way of the following examples. The basic idea is that derivations are like spreadsheet cell formulas, in that they set up reactive logic:

Watch, React, and Chain: Reactive logic watches for changes to referenced data and adjusts the derived data accordingly. This can chain when the adjusted data is itself referenced by other derivations.

The reactive logic tutorial examples illustrate the key design patterns for reactive logic. Review these concepts so that you have them at your disposal when addressing complex logic.

You might want to keep a list handy of the Live Logic rules.

For more information:

Accessing related data

Use formulas to access other values in the same row. Often useful, but most interesting transactions involve data from a related table. Consider the following example:

Multi-table derivations are automated by rules, based on relationships (either Foreign Keys defined in databases, or Virtual Foreign Keys):

    • Parent Access to Child Data - when you define aggregates (sum, count, min, max), the child watches for changes to referenced child values, and, when necessary, adjusts the parent.
    • Child Access to Parent Data - when a child formula or validation references parent data (for example, parent.attributeName), the parent watches for changes to attributeName and propagates changes to all the child rows. Such propagation does not occur for Parent Copy derivations.

Forward Chaining: Constraining Chained Derivations Pattern

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

Access data from related domain objects using Business Logic services:
  • 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.
For more information about automatic adjustment processing and parent adjustments, see Logic Execution.
  • Formulas support parent references. Automatic Cascade processing occurs when the parent row's reference data is changed.
For more information about parent references and child cascading, see Logic Execution.

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 validation.
  • The Bill of Materials Explosion (see rules 1 and 2) requires identifying whether a Product is a kit and has any components.

Replicate Junction Pattern

The relational model supports many-to-many relationships by introducing junction tables: a table with foreign keys to both end-points. For example, in the sample database, orders can have many Products, and a Product can be ordered on many Orders. The Junction Lineitem has foreign keys to both, as well as additional attributes (such as QuantityOrdered).

For more information about the sample database, see Sample Database.

You can introduce junction tables for many-to-many relationships between two endpoint objects. It is often a requirement that an endpoint object needs to sum/count an attribute from the other endpoint. Since sums/count operate on 1:n relationships and not n:m relationships, replicate the summed attribute into the junction.

The replicate can take the following forms, depending on whether the sum should reflect changes in the summed attribute. The Reactive Logic Tutorial illustrates both.

  • 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 kit 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. 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. Changes to parent references are cascaded to child rows, unlike @copy logic as shown in the next example.

For more information:

  • Do not reflect summed changes into sum: use @ParentCopy

The Place Order example illustrates a many to many relationship between Orders and Products, where Lineitem is the Junction entity. Orders.amountTotal is the sum(Lineitems.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.

For more information:

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.

You can extend this pattern to non-database use cases, for example commands.

Form Flow based on Derivation Results

It is a 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.

Derivations fire only when you save a transaction. We recommend using the Ready Pattern.

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 (for example, a conditional transition, or to cause hiding of not-relevant portions of the screen).

It is undesirable to hold an open database transaction (and blocking locks) over screen transitions. Given that you need the business logic derivation results, 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 (for example, adjust General Ledger, the Customer Balance, Product stock) until all the screens are complete.

We have all seen such an example in online 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.

Best Practice:

  1. Define a isReady attribute (for example, in Purchaseorder). Its value is false until the checkout screen, at which point it is set to true.
  2. When defining rules, predicate the rules on isReady == true as in the "Place Order" business transaction:
    Derive Customer.balance as Sum (purchaseorders.amountUnPaid where isReady=true)
  3. Provide a Make Ready (aka "checkout") transaction to activate the remaining logic.
    For more information about Make Ready transactions, see Reactive Logic Tutorial.

Commit Time Logic: Validations, Actions

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. Requirements such as No Empty Order (which depend on the count value) need to use Commit Validations.

For more information:

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.

Complete the following steps:
  1. Create a "scalar" Domain Object (e.g., Parameters), with attributes you want authorized Business Users to change, such as discountAmount.
  2. Provide access to this object in your applications' user interface.
    Define your Logic Classes to extend LogicBase (see BusLogicIntro), where LogicBase implements the method to return the single Parameters object
    You can use getParameters() in formulas (just as Parent references), for example, getParameters().getDiscountAmount()
    Create a 1 row Domain Object (e.g., Parameters).
  3. Provide getParameters() in superclass of Logic Classes.
    Use LogicBase in formulas.

Data Integration

Resources to define Partner object mappings

RESTful APIs are an excellent mechanism for interacting with other systems, both as a receiver and as a sender. You employ the JavaScript aspects of reactive logic, and described in this JavaScript Integration Example.

For more information:

MetaData tags for Matching

You can match incoming data to target data using these services, for example to locate parent data, or insert/update master data.

For more information about how to match incoming data, see Complex Transactions.

Group By

You can store subtotals that are incrementally maintained as updates occur, using the Group By Pattern. For example, you might wish to maintain total sales for each sales rep for each month.

For more information about an example of how to maintain total sales for each sales rep for each month, see Reactive Logic Tutorial.

Extensibility

The following sections describe patterns implemented by the extension package. These are common patterns and illustrate how to provide logic extensions.

Allocation

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, by way of chained allocationsallocate their allotment to designated General Ledger accounts)
Business Logic supplies allocation as an extension.

For more information:

Insert From (copy)

It is a 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 a copy of the current row, under the proper conditions. Acommon example is 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 existing one.
  • Bill of Materials explosion. This is 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.
For more 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 two child collections of languages: spokenLanguage and translatesLanguage. You can 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, you can ensure that a component is not also the containing part.

Live API Creator provides a set of logic services for FindWhere that you can use 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).

For more information about the FindWhere operation, see findWhere.

ċ
Screen Shot 2015-10-28 at 12.41.54 PM.png
(162k)
Val Huber,
Feb 16, 2016, 2:12 PM
ċ
relatedData.png
(106k)
Val Huber,
Feb 16, 2016, 2:12 PM
Comments