Logic Patterns

Logic Patterns
lac51
Explore the design patterns of reactive logic in the context of running examples, such as those provided in the reactive logic tutorial. Experiment with real transactions, and study the logs, using the provided API samples.
In this article:
 
 
3
 
 
Concept: Think Spreadsheet
You can write event handlers to handle table updates. Experienced API developers understand them instantly. The key to getting value out of 
Layer7 Live API Creator
 is to use event handlers with spreadsheet-like rules. This concept is called "think spreadsheet." A good way to understand it is by way of the reactive logic tutorial examples, which illustrate the design patterns for reactive logic. 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. Reactive logic can chain when the adjusted data is itself referenced by other derivations.
For more information:
Access Related Data
Access other values in the same row using formulas. Often useful, but most interesting transactions involve data from a related table. The following image illustrates an example:
  
Multi-table derivations are automated by rules that are based on relationships–either from foreign keys that you define in your database or from relationships you add using API Creator.
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. This propagation does not occur for parent copy derivations. 
For more information: 
Forward Chaining: Constraining Chained Derivations Pattern
Probably the most common pattern is defining a validation that requires a series of dependent derivations to produce the data that is 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:
  • You can enable parent objects to aggregate related child data using sum and count rules. Automatic adjustment processing occurs when child rows are changed in such a manner.
  • You can create parent references using formula rules. Automatic cascade processing occurs when the parent row's reference data is changed.
For more information:
Concept: Counts for Existence Checks
The count derivation can produce a count of related child rows, optionally qualified by a condition. Often, the objective is to know whether the count is zero or non-zero - that is, are there any [qualified] children. For example:
  • The No Empty Orders requirement is implemented by a countItems, which 
    Layer7 Live API Creator
     checks in a validation rule.
    For more information about this requirement, see No Empty Order Example.
  • The Bill of Materials Explosion (see rules 1 and 2) requires identifying whether a Product is a kit and has any components.
For more information about count derivations, see Count Rule Type
 
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 and extra attributes (such as QuantityOrdered).
You can introduce junction tables for many-to-many relationships between two endpoint objects. Typically the requirement is that an endpoint object must 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 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 must sum its components price to determine its own price.
Because 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.
  • 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 want 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, or command pattern, invokes behavior from the creation of command objects. These patterns are commonly used in text editors, for example, to turn a set of characters bold or italic. You can maintain these objects in a list and can use them for undo, for example.
 You can use this same pattern in data processing applications. You insert the request object, which represents a transaction requesting some behavior, such as a credit request, or give an employee a raise, call a series of external services, or run scheduled tasks in the background. Instead of code, you implement the desired behavior by declaring logic.
 You can extend the request pattern to non-database use cases, for example commands.
For more information:
Form Flow based on Derivation Results
It is a common requirement to drive or flow based on derivation results. For example, you can define a wizard for document processing, with tab sheets enabled/activated on the basis of whether restricted Products are ordered, or the customer credit history.
You can compute the data used to drive these conditional transitions using derivation mechanisms. 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. The presentation layer uses these derivations for display and 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 requirement suggests that you should submit and commit changes at the completion of screen-1. But this requirement presents a problem. It might not be appropriate to post this incomplete transaction (for example, adjust General Ledger, the Customer Balance, Product stock) until you have completed the screens. This scenario is common in online shopping. You can fill your cart and see how much things cost (a derivation) as you shop. Only when you checkout is your account charged.
Best Practices:
 
  • Define an 
    isReady
     attribute (for example, in 
    Purchaseorder
    ). Its value is false until the checkout screen, at which point it is set to true.
  • 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)
  • Provide a Make Ready (aka "checkout") transaction to activate the remaining logic.
    For more information about how to provide a Make Ready transaction, see the Logic Tutorial.
Commit Time Logic: Validations, Actions
Logic processing begins with the logic phase (initial row processing) and ends with the commit phase (after all rows are processed). Counts of inserted child rows are always zero (0) during the logic phase. Requirements such as No Empty Order (which depend on the count value) must use commit validations.
 For more information:
Parameterized Formulas
You can enable business users to alter data that is used in formulas. For example, you can apply a 
discountAmount
 to a purchase order.
  1. Create a "scalar" domain object (for example, 
    Parameters
    ), with attributes you want authorized business users to change, such as 
    discountAmount
    .
  2. Provide access to this object in your applications' user interface.
  3. Extend 
    LogicBase
     (see BusLogicIntro) by defining your logic classes, where 
    LogicBase
     implements the method to return the single 
    Parameters
     object.You can use 
    getParameters()
    in formulas (just as you can parent references), for example, 
    getParameters().getDiscountAmount()
    .
  4. Create a one-row domain object (for example, 
    Parameters
    ).
  5. Provide 
    getParameters()
     in superclass of Logic Classes.
  6. Use 
    LogicBase
     in formulas.
Data Integration
You can integrate data in the following ways:
  • Use resources to define partner object mappings. You can interact with other systems, both as a receiver and as a sender, using the RESTful API mechanism. You employ the JavaScript aspects of reactive logic.
  • Use metadata action tags for matching. You can match incoming data to target data using metadata action tags, for example, to locate parent data or insert/update master data.
    For more information about how to match incoming data, see Complex Transaction Processing.
Store Subtotals using the Group By Pattern
You can store subtotals that are incrementally maintained as updates occur, using the Group By Pattern. For example, you can maintain total sales for each sales rep for each month.
For more information:
Extensibility
The extension package implements the following common patterns. The patterns illustrate how to provide logic extensions.
Allocation
The allocation pattern can be summarized as follows:
Allocates a 
provider amount
 to designated 
recipients
, creating 
allocation objects
 (a Provider/Recipient Junction) for each such allocation.
For more information about the 
allocateFromTo
 system method, see The allocateFromTo System Method.
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. These child rows require proper initialization of their attributes. 
For more information about the 
InsertIntoFrom
 system method, including the auditing, deep copy, and bill of materials explosion services, see InsertIntoFrom System Method.
Inclusion/Exclusion Logic
You can search through a list to find rows that match a specified criteria using the 
FindWhere
 system method. 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
 system method, see findWhere System Method.
RPC-style APIs: Functions, Event Sourcing
In addition to altering data using create, read, update, delete (CRUD) services, you can create a more explicit API. These are sometimes referred to as an RPC-style API. You can do this:
  • Using functions. You can associate functions with tables and/or custom resources and alter the supplied table row.
    For more information about how to associate functions with tables or resources, see Manage Functions.
  • Using the Event Sourcing pattern. This pattern seeks to retain persistent data for each transaction for audibility. In addition to an Employee row, you have a series of child rows of EmployeeSalary changes.
    For more information about the event sourcing pattern, see Command Pattern.
For more information about how to use functions and the Event Sourcing pattern, see Employee Raise Example.