Business Context
Story: Place Order.
Task/Requirement: Check Credit. (or, your methodology / terminology).
Business view
When placing an order, check credit - elaborated as follows (the "cocktail napkin spec")...
- the Balance must be less than or equal to the Credit Limit, where... (step-wise definition of terms)
- the Balance is the sum of the unpaid Order Amount Totals, where...
- the Amount Total is the sum of the LineItem Amounts, where...
- the Amount is the discounted Price * Quantity, where...
- the Price is obtained from the Product
A good spec - clear, concise.
Conventional Design
In a conventional approach, you might design the following pseudocode:
- Compute the LineItem.amount
- Read the Product to get the Price
- Multiply by qty_ordered to compute the amount
- Update the PurchaseOrder.amount_total
- Read the PurchaseOrder
- Increase the amount_total
- Update the PurchaseOrder (to cache)
- Update the Customer.balance
- Read the Customer,
- Increase the balance
- Update the Customer (to cache)
- Check that balance <= credit_limit
- Throw exception with error message for UI handling
- Rollback the transaction
But Place Order is just one Story. We need analogous logic for all the related Stories (Detete Order, Pay Order, etc etc).
Reactive Rule Approach
And that's the power of declarative reactive logic. You simply state the rules below (nearly the same as the cocktail napkin).
Reactive Rule Execution: Watch, React and Chain
And (as in a spreadsheet), the rules are automatically applied to all incoming transactions:
- They watch for changes in data referenced by rules
- They react to changes in referenced data. Execution order is dictated by dependencies.
- They chain - including across tables. So changes to line items affect their order, which affect their customer
Note it works across tables. Consider the customer balance - the sum of the unpaid order amounts.
It works rather like a spreadsheet. Order changes are watched, and the balance is
- increased when order inserted
- decreased when order deleted... or paid
- adjusted when the order amount total is changed... or assigned to a new customer... or the line items are altered
Observe persistence is automated (no need to read/write the customer, or deal with transactions). And it's optimized:
- adjustments are 1 row updates, not select sum queries
- sql is averted if the watched data is not changed
- caching is provided (inserting multiple line items results in just 1 adjustment to order and customer)
Bottom Line
That means the following Stories are automatically addressed with our 5 "cocktail napkin" rules:
- Delete Order - the balance is reduced
- Pay Order - the balance is reduced
- UnPay the Order - balance is increased
- Reassign Order to a new customer - new customer balance increased, old balance decreased (for unpaid Orders)
- Reassign a Line Item to a different Product - adjusts the order's amount total
- Add a Line Item
- Delete a Line Item
- Change Line Item Quantity
- Reassign Product to Line Item
- Do multiple of these, in combination ("no, 2 hammers, not 1 shovel")
A conventional approach would require hundreds of lines of code, might easily miss corner cases, and be tedious to maintain.