enforces database integrity on RESTful update requests - business rules for derivations and validations (conditions that must be met for successful transaction commits). Logic is reactive:
- You bind spreadsheet-like expressions to database columns
- Automatic Change Propagation: the system automatically adjusts data when referenced data is changed (which can chain)
- Change Propagation includes references in other tables - SQL and transaction bracketing are automated
You do not directly invoke reactive or event logic - it is automatically executed by the service on processing updates.
Update logic is complementary to other forms of business logic such as process (workflow) logic, application integration, and decision logic.
You can jump directly to the Reference, which provides links to each rule type, as well as tutorials and training. After reading this page, you may also wish to explore the architecture. This page provides a basic background on business logic - its key elements, its key characteristics.
Use the Logic Designer
(illustrated at right) in your Browser to specify logic (sum example shown here
). Changes are affected instantly, without the need for code generation or deployment.
A First Look at Logic
The sample problem
(Customers, Orders and Parts) illustrates the use and operation of business logic. Logic is expressed as a set of spreadsheet-like expressions that define what your data means.
Consider the Use Case Place Order, with the requirement Customer's balance may not exceed their credit limit. The following logic, which looks rather like a requirements document, is fully executable:
Validations are expressions that must be satisfied to commit transactions (else an exception is thrown). Far beyond simple single-attribute validations, the requirement is multi-attribute validations, such as this Customer Validation:
balance < credit_limit
Validations are the most familiar form of business logic, but derivations and events are the most valuable, per dependency / re-use automation noted below. Derivations here include multi-table derivation rules such as in this rule which defines the balance as the sum of the unpaid order totals:
sum(purchaseorder.amount_total where paid = false)
Derivations are conceptually similar to spreadsheet cell formulas. Note that:
- Derivations are multi-table, as in the example above
- Derivations can chain, both to validations, and other derivations:
Purchaseorder.amount_total = sum(lineitem.amount)
Lineitem.amount = qty_ordered * product_price
Lineitem.product_price = copy(product.price)
- Chaining, ordering and dependencies are automatically handled (further described below)
- Derivations can include if/else logic, state transition logic, and reference related data
- Derivations are highly optimized to eliminate / optimize SQLs. For example, changing an orders's date does not retrieve the customer, and paying an order adjusts the customer with a 1-row update -- not an aggregate query
You declare the logic in the Browser as shown at the top of this page. Dialogs
make it simple to define, and the system produces this documentation automatically.
So logic is not only executable, it is transparent documentation that enables Business Users and IT to partner and find missing / incorrect elements.
Most computer programs are imperative: an ordered, optimized set of instructions on (exactly!) how to do something. Procedural. 4GLs and object oriented languages are powerful, but imperative.
"What", not "how"
By contrast, declarative means that instead of coding how to do something, you declare what you want to achieve. As we saw in the example above, you simply specify
balance as the
sum(purchaseorders.amountUnPaid where isReady = true). You do not stipulate when to run it, or how (SQL read/writes, arithmetic, etc).
There are two key declarative technologies employed: Constraint-based programming, and Reactive Programming.
Let's consider Validations. A good technology to apply is Constraint Programming, where we state conditions that must be true at some end state. For Web Service Transactions, we simply specify a set of table expressions that must be true at the familiar end-state called commit (else an exception is returned, and the transaction is rolled back).
Derivations are significantly more complex than validations, since they can be inter-dependent and must therefore be executed in a proper order. Change detection and dependency management is a large portion of business logic - high volume tedium and complexity. Here is a real opportunity to simplify and accelerate by applying innovative technology.
And one exists: Reactive Programming is a perfect solution for Dependency Management. In such an approach, you define the meaning of a variable (e.g., A = B + C). Unlike procedural code, this stipulates that subsequent changes to B or C are watched - if changed, A is recomputed, which may of course chain to variables dependent on A.
Reactive Programming is an automation of the Observer Pattern used to manage dependencies. It most successful application is the spreadsheet, where cell formulas are Reactive Expressions that provide enormous power yet are very simple.
This technology maps naturally onto database transaction processing by assigning Reactive Expressions to database columns. Recall our logic defining the customer balance as the sum of the unpaid order totals. It's not a free-standing SQL statement: it defines the meaning of your data.
So, once you declare the expressions, it's the Logic Engine's job to figure out how to make these constraints become true. For derivations, this means dependency management - it watches for changes to referenced data, then (to keep the derivation constraint true), and makes the compensatory changes.
That is a significant statement. In the case of our
customer.balance rule, this means that this one statement obligates the system respond to all of the following:
- Order inserted - balance increased
- Order deleted - balance decreased (if not paid)
- Order paid - balance decreased
- Order unpaid - balance decreased
- Order amountTotal changed - balance adjusted
- Order reassigned to different customer - balance increased for new customer, decreased for old
Even more powerfully, logic constraints can chain, since one constraint can reference the value of another constraint. So, there are dependencies between constraints. In our example above, the
Customer.balance refers to the
Purchaseorder.amount_total, itself defined by a constraint. So, a change to the
Lineitem.amount affects the
Let's further explore the implications of this declarative approach to logic using Constraint and Reactive Expressions.
Example: Reassign Product
This example will enable us to explore business logic. When a Line Item qtyOrdered is updated, the resultant logic (shown here) recomputes the Order.total and Customer.balance, and checks the credit.
This is fully automated - no code is required. The system processing is essentially a highly optimized version of forward chaining:
- Detect what has changed
- Determine the attributes dependent on what has changed - including across tables
- Recompute these, in an order that reflects their dependencies
- Recurse for further dependencies
Let's see how the "First Look" logic above - design to address Place Order, solves change quantity.
Customer.balance rule, perhaps declared for Place Order, simply states that its value is the sum of the unpaid orders. This design intent is encapsulated into Purchaseorder, and then automatically re-used over all related transactions. So, the balance is increased if an order is added, decreased when it is deleted or paid, and so forth.
Put another way, Logic is associated with your tables, not with a specific transaction or request type. This is what enables logic re-use.
So our "First Look" logic above, perhaps conceived for Place Order, is automatically re-used for all these related transactions:
- Delete Order - the balance is reduced
- Pay Order - the balance is reduced
- Reassign Order to a new customer - new customer balance increased, old balance decreased (for unpaid Orders)
- Reassign a Line Item to a different Product (see above)
- Add a Line Item
- Delete a Line Item
- Change Line Item Quantity
This "design one / solve many" applies to maintenance as well: when you change to your logic, the system automatically reflects it in all the relevant transactions.
Another perspective on re-use is active enforcement. Business Logic is not invoked by direct call. Espresso Logic analyzes all incoming put/posts, and applies your business logic automatically. This helps ensure integrity - compliance officers can be confident the logic is always executed. By contrast, integrity you invoke manually is essentially elective, so can be inadvertently skipped.
Active Enforcement means that active enforcement of logic (above) and security semantics are not provided by special API calls that can be inadvertently forgotten. In essence, your data becomes smart enough to enforce its own logic and security under a standard REST?JSON interface.
Automatic Dependency Management, Ordering
In traditional coding, the first thing you do with an incoming transaction is to detect changes to see if anything depends on that. So, as illustrated in the Logic Example, re-assigning a Lineitem product requires we recompute the
amount. And things chain, across tables: the changed
amount requires we recompute the
Orders.total. and then the
Another term used for this processing is Forward Chaining.
And this must all be ordered, again based on dependencies. In our example, we can only calculate the amount after recomputing the price. While simple in this case, dependencies rapidly become very complex, which is why maintenance is such a challenge.
With Espresso Logic, all this is automated - no code.
Every time you change the logic, the system recomputes the change detection and dependency ordering. This works not only within a row, but across rows to address multi-table transactions.
While a small example, such automated multi-table dependencies, automatically re-used over multiple Use Cases, addresses the key challenge for transactional business logic. It is this automatic change detection / propagation - with optimizations - that enables 5 logic specifications to replace 500 lines of code.
Your rules simply reference related data. You do not stipulate when or how to read or update the data. In our example, you do not write script or 4GL to read the Order or Customer - this is fully automated.
The Logic Engine is thus similar to a relational database query engine's optimizer. This not only eliminates such elements from your logic, but it enables - in fact, obligates - the system to perform global optimizations as described below.
Much of the power of declarative logic is automating multi-table relationships, using rules like parent references, sum and count, and parent copy. These all rely on foreign key definition in your database. See Database Design for more information.
As for database retrieval, a declarative statement enables the system to provide global optimizations to reduce and optimize SQL operations. In our example, the computations of the
Customer.balance are 1 row "adjustment updates", not aggregate SQLs.
Unlike manual systems that often degrade over time due to the costs of re-optimization, Business Logic is automatically re-optimized on each change, so performance remains high. So, for example, you can alter the "stored vs computed" decision instantly, where such a change would require massive re-coding in a traditional procedural approach.
Transparent - with logic filtering
Unlike code, logic is transparent to Business Users. This provides important opportunities to engage them in a project, both for design, compliance verification, and system documentation.
You can facilitate such communication with rule documentation. The system enables you to filter logic on the contents of your description, so that you can focus on the rules relevant for a particular discussion.
Contrast to Traditional
Without such declarative automation, your procedural code must perform all of this dependency management, ordering, change detection, and optimization - over all the Use Cases. This is how 5 rules can represent hundreds of lines of code
Rules are not implemented by code generation. They do not require compilation or deployment - they are active as soon as you save and activate.
Rules are maintained in the Repository. They can be managed via a RESTful API, or by Project Export.
You can categorize rules into Topics
, and filter them by topic.