home‎ > ‎

Declarative

This contrasts Procedural vs. Declarative approaches to Business Logic.


 
 


Procedural

In procedural programming, considerable design attention is invested determine when and in what order to invoke logic, how to assure re-use, and in optimization.  This manual approach to dependency management is common to a broad class of languages, including 3GLs, 4GLs, and modern object oriented languages such as Java.

These design considerations exist not only for initial build, but on each iteration cycle. Such manual design - and re-design - is costly, and provides ample opportunities for errors.


The high cost of "how"

It has often been noted that Procedural approaches require you to encode "how" to do something, rather than "what" as in a Declarative approach.  A brief example will illustrate the implications.

Imagine that our Analysis uncovers that we need to compute the Customers' balance, in order to check it against the credit limit.  The "what" is very simple: derive the balance as the sum(purchaseorders.amountUnPaid where isReady = true).

The "what" is not so simple, and incurs a number of costs:

  • Analysis effort: Identify related Use Cases

While we may have encountered this while analyzing Place Order, we need to be sure it is followed in the related Use Cases:

  1. Delete Order - the balance is reduced
  2. Make Order Ready - the balance is increased
  3. Pay Order - the balance is reduced
  4. Re-assign Order - old customer balance reduced, new balance increased
  • Design effort: non-trivial

There are complex design decisions about how to enforce the logic - introduce a service layer?  Build Data Access Objects?  Utilize Hibernate events?

    • Quality: compromised by manual design
    Errors are inevitable in a manual process.  In the example, above, we forgot the case of re-assigning a Purchase Order to a new customer: we need to decrement the old customer's balance, and increment the new customer's balance.

    The implication of forgetting this is catastrophic: the database does not "add up", leading to bad business decisions and worse.
    • Coding effort: a simple sum can require 4 pages of code
    The agility factors here are daunting: a single decision - just one sentence - can require 8 days of effort!  The root cause is Dependency Management: your code must detect every change - in every case - and arrange to trigger required logic.  In a declarative approach, Forward Chaining is automatic.  So, for example, a simple Sum (1 line Logic Rule) requires 4 pages of Java code.
    • Change agility

    It is a classic in applications development: should derived aggregates be stored or computed each time?  Historically, this is a trade-off of speed (store the aggregate so changes are adjustments rather than aggregate queries) vs quality (bugs can compromise data integrity, as noted above).  Despite our best efforts, it is inevitable that we make the wrong decisions, where these are often visible only in the late stages of a project (e.g., load testing, going live, etc).

    Reversing such design decisions is very expensive, since it requires you:

    1. Find all the code where the decision was implemented (not so easy in hundreds of thousands or millions of lines of code)
    2. Recode
    3. Re-test
    • Maintenance effort
    Each maintenance (or iterative development) change requires re-design:
    1. Ordering: how to introduce new code, and manage the interactions with existing code
    2. Re-use: where must I make similar changes
    3. Performance: often a change invites re-visiting basic approaches, though time pressures often mean this is not feasible, so that systems performance slowly degrades over time



    Spreadsheets show the way

    It has been many decades since we wrote programs to perform business analytics. No one today would dream of writing a Basic program to add up a table of numbers.

    Yet we do it all the time for data processing.

    The breakthrough for Spreadsheets was the realization that to enable the End User to declare how their data is compute with simple derivations. The spreadsheet supplies the chaining: when any referenced data is altered, the value is recalculated.

    Automated Business Logic brings the same paradigm - and the benefits of agility and transparency it confers - to Business Logic. 

    Declarative

    5GL: Constraint based language

    Some characterize a 5GL as a constraint-based language, where you tell the computer what to do, not how.  

    Note that is a language characterization that applies not only to ABL constraints but also to derivations: derivation logic can be viewed as a constraint the system is to "make true" by the end of the transaction.

    By contrast, Business Logic is declarative. It is un-code: uncalled, unoptimized, unordered (but not unloved!). Not only does this supplant a large volume of code, the Business Logic Engine automates the design activities described in the sub-sections below.


    "What", not "how"


    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).    

    Automatic Ordering

    Logic can be chained: 1 rule can depend on another, even across tables.  For example, the Customer balance is a chained aggregate: derivation that sums (refers to) the Purchase Order totalAmount, itself a derivation that sum Line Item amounts.  And, it must be evaluated before the Credit Limit Check.  So these must all be executed in the proper order to produce the correct result.

    When your Business Logic Component is first loaded, the Business Logic Engine invokes the Dependency Analyzer to determine a proper order of execution. Your rules can be specified in any order within your Business Logic Component.


    Automatic Invocation

    Business Logic is not invoked by direct call. Hibernate invokes the Business Logic Engine as an event, which in turn invokes your logic. This helps insure integrity: integrity you invoke is essentially elective, as opposed to Business Logic which is automatically invoked whenever any update is made - regardless of transaction source (interactive vs. message), service, etc.


    Automatic Re-use

    Re-use is a core development objective, requiring substantial design effort in procedural approaches to maintain critical database integrity.  It is certainly not automatic. Business Logic, however, operates as an Event Handler, so logic enforcement and re-use is automatic.  This re-use occurs at the level of both code and design, as described below.


    Code Re-use - over transaction source

    Object oriented languages provide this re-use, by requiring all accessing code to use an objects method.  Hibernate events enable an analogous level of encapsulation with events.

    Automated Business Logic employs these to assure that all Hibernate-based updates are subjected to the Business Logic you specify.  Such automatic invocation guarantees integrity regardless of transaction sources (customers get the same answer regardless of the interaction):
    • Interactive business logic is not required in page actions, avoiding the anti-pattern of business logic in page actions which cannot be used for message-based transactions

    • Message-based - services automatically re-use the domain logic, so that services are thin


    Design Re-use - over transaction type

    Even more powerful - and much less common - is encapsulation of not just code, but design intent.  This arises since your logic is declarative: you declare what the affect should be, not how (the methods that implement it).  The power of this is best illustrated by a deceptively simple example.

    The Customer.Balance rule, perhaps declared for Place Order, simply states that its value is the sum of the unpaid orders.  It does not tie this to an algorithm, enabling the system to optimize with efficient approaches such as adjustment.  Nor is the rule tied to a particular method (Use Case) - it's design intent applies to all transaction types.

    This design intent is declaratively encapsulated into the Order Domain Object, so that it is automatically re-used over all these related transactions:

    1. Delete Order - the balance is reducedPay Order - the balance is reduced
    2. Reassign Order to a new customer - new customer balance increased, old balance decreased (for unpaid Orders)
    3. All the various cases of Change Order:Change a Line Item Quantity
      1. Change a Line Item Part
      2. Add a Line Item
      3. Delete a Line Item

    So, when you make a maintenance change to your logic, the system automatically reflects it in all the relevant transactions.



    Automatic Optimization

    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, in contrast to the quandary incumbent in the procedural approach.


    The real value is that these services are repeated on every logic change, resulting in Maintenance Automation.


    Toward Executable Requirements

    Our Automated Business Logic mission, then, is not restricted to providing services to increase agility with high performance.  Our goal is to enable you to express requirements that are executable, stated in business terms so that they are transparent to Business Users, developed with the agility of thought, changed just as easily, delivered within an architecture that is powerful, easy to adapt, and provides enterprise level performance.

    Declarative makes this possible.
    Comments