Logic Bank is a Python package for SQLAlchemy ORM that automates transaction logic — complex multi-table derivations, constraints, and actions such as sending mail or messages. Logic consists of:
If you’ve ever written a web app on top of a database, you know how much work it is. About half the effort is in the UI, and about half in backend transaction logic - complex multi-table derivations, constraints, and actions such as sending mail or messages.
There are ORM frameworks such as SQLAlchemy that simplify database access, but the domain logic itself remains domain-specific code. You might code it in triggers and stored procedures, in SQLAlchemy events, or in UI controllers. However you do it, such legacy approaches are slow to build and change, tedious, and error-prone – business friction.
It’s easy to dismiss this business friction — “domain-specific logic requires domain-specific code”. But what’s hard to dismiss is that we can state specifications that are clear, concise and complete.
Consider this specification of the check credit requirement, typical of so many transactions - we roll up some values and apply some constraints:
Our cocktail napkin spec is really nothing more than a set of spreadsheet-like rules that govern how to derive and validate our data. And by conceiving of the rules as associated with the data (instead of a particular UI button), we address all of these Use Cases:
The legacy implementation of this spec turns our 5 simple, transparent rules into over 200 lines of code (view them here):
And that’s the problem Logic Bank is trying to solve: let’s make these rules executable.
We’re introducing Logic Bank, an open source Python package that automates a shocking amount of this tedium, and goes far beyond the usual CRUD-in-a-box approach offered by other solutions.
Using Logic Bank, you can declare advanced back-end behavior using reactive spreadsheet-like rules. And customize them with Python. You can even build a basic web app in literally minutes. And your logic-aware database access layer is the perfect foundation for creating APIs and custom UIs.
The level of agility offered by this approach is, we believe, unparalleled, with sufficient potential to influence your choice of technology stack.
Since transaction logic is nearly half of most database systems, and rules automate over 95% of the logic 40X more concisely, Logic Bank can return remarkable savings in time and cost.
These are substantial claims. Let’s put them to the test. First, let’s see what you do to use Logic Bank, and how Logic Bank executes your logic. Then, let’s ask:
To illustrate, we’ll use the check credit example above.
Logic is declared as spreadsheet-like rules as shown below (lines 34-48) from this example, which implements the check credit requirement (the balance - a rollup of unshipped order totals - cannot exceed the credit limit). This is exactly our cocktail napkin spec, expressed in Python (here shown in PyCharm, a Python IDE):
To activate the rules (declare_logic
is the function shown in the screen above):
Java
1
LogicBank.activate(session=session, activator=declare_logic)
Observe these are not simple single-field validations - they address complex multi-field, multi-table logic.
Logic Bank operates as a plugin to SQLAlchemy events:
sqlalchemy
for inserts, updates and deletes.before_flush
events on Mapped Tables.
Logic expressed in Logic Bank does not apply to updates outside SQLAlchemy, nor to SQLAlchemy batch updates or unmapped sql updates.
Let’s see how. Consider inserting the OrderDetails for an order: roll up to AmountTotal / Balance and check credit:
The diagram illustrates chaining as each OrderDetail is inserted:
OrderDetail.UnitPrice
(copy, line 43) references Product, so inserts cause it to be copiedAmount
(formula, line 42) watches UnitPrice
, so its new value recomputes Amount
AmountTotal
(sum, line 40) watches Amount
, so AmountTotal
is adjusted (more on adjustment, below)Balance
(sum, line 37) watches AmountTotal
, so it is adjustedWe have 2 data points we can examine:
The 5 rules above represent the same logic as 200 lines of Python legacy code - view them here. This 40X (5 rules vs. 200 lines) is proportional - even in a medium sized system, this is tens of thousands of lines of code. Such code is a corporate liability - it reduces time to market, is costly to develop and maintain, and is not transparent to business users.
This 40X is quite striking. It comes from automated dependency management, and automatic reuse.
Rules automate all of the dependency management — see which attributes have changed, logic ordering, the SQL commands to read and adjust rows, and chaining are fully automated by the engine, based solely on the rules above.
Note rules address not only “add,” but are automatically reused overall related transactions such as “update” and “delete.” In fact, these 5 rules automate all of these Use Cases listed above (add order, ship / unship order, re-assign order etc).
While such reuse over Use Cases is automatic in Logic Bank, it requires considerable code in legacy approaches. And worse, it’s easy to miss corner cases, e.g., “re-assign an Order Detail to a different Product with a different quantity” requires tricky adjustments to the Order.
Finally, consider clarity. The legacy code is not just tedious - all you can see is “how it works.” That’s a problem, since it obscures the critical point: “what is it trying to do?”.
By contrast, rules are an executable specification - the “what” is clear for maintenance, and for business users. As Chris Date puts it in his book that champions the use of rules, the proper focus is What, Not How.
It’s always easy to cherry pick an example. It’s usually hard to have confidence that these results are borne out in real projects.
But in this case, there is some interesting evidence. Logic Bank is built on a technology with a proven track record of success:
The Versata metrics are particularly interesting:
Logic Bank brings the same technology to the Python/open source community. Let’s see how this implementation addresses Extensibility, Scalability, and Manageability.
While rules automate much, they don’t automate _everything. _Every app has elements that integrate with outside systems, such as sending mail or messages.
The screenshot above (see heading - “Declare Rules Using Python”) includes a rule on line 45 that invokes the Python function on line 26. So, whatever you can’t do in rules, you have the full power of Python.
We typically think of scalability in terms of clustering. And containers like Flask support that.
But all the clustering in the world cannot cover inefficient database access.
Let’s face it, many automation initiatives have failed to provide effective automation for transaction logic, including Rete-based rule engines, and Object Relational Managers (ORMs). The primary issue has been scalability: excessive and expensive SQL queries.
However, Logic Bank is specifically designed to address this. Let’s see how.
sum
queries)The Customer.Balance
sum rule (line 37) “watches” changes to Order.AmountTotal
- a different table. So, the “react” logic has to perform a multi-table transaction, which brings our performance issue to bear.
As is commonly the case (e.g. Rete engines, some ORM systems), you may reasonably expect this is executed as a SQL select sum
.
In Logic Bank, it is not.
Instead, Logic Bank optimizes it as an adjustment: as single row update to the Customers balance. This optimization dramatically reduces the SQL cost, often by orders of magnitude:
select sum
queries are expensive - imagine a customer with thousands of Orders.In addition, Logic Bank provides _automatic pruning. _If an update occurs that does not affect the sum, no SQL is issued at all. Contrast this to ORM / Rete engines, where the typical approach is to run all the sum queries, all the time.
The “Declare Rules” screenshot shows that rules are defined in Python. You can use standard source control systems and procedures to manage your logic. There are no databases, xml or json files to configure and manage.
Python has recently been extended with type support, enabling your IDE to provide code completion, and spot many errors. Logic Bank uses this type support (see line 26).
The “Declare Rules” screenshot also illustrates that you can stop in your rule logic (the red dot on line 29), and use your IDE (here, PyCharm) to see variables, step through execution, etc.
In addition, Logic Bank logs all rules that fire, to aid in debugging. If we run add_order.py
, we get the following log (see the lower pane in the following screenshot):
The core tenant of agile is working software, driving collaboration, for rapid iterations. Here’s how Logic Bank can help.
The examples above illustrate how just a few rules can replace pages of code.
Certainly business users are more easily able to read rules than code. But let’s face it, rules are still pretty abstract.
Business users relate best to actual working screens - their interpretation of working software. The fab-quick-start project enables you to build a basic web app in minutes, like this:
Rules are self-ordering - they automatically recognize their interdependencies, and order their execution and database access (pruning, adjustments etc) accordingly. This means:
Legacy code is a liability: costly to write, hard to change, and not transparent to Business Users. And tightly bound to a technology platform (language, architecture, etc).
Logic is a corporate asset: reduced time to market, reduced cost, easier to change, and transparent to Business Users. Logic helps you cope with business change.
And since it is declarative, Logic largely technology independent:
So Logic can not only help cope with business change, it can also help cope with technology change.
Logic Bank is useful pretty much anywhere you are processing database transactions:
In far too many web apps, legacy logic is placed in the buttons (controllers). This means it is hard to share between apps, and impossible to share with not-UI services such as APIs. It’s an architectural bug.
Logic Bank encourages logic to be centralized in SQLAlchemy, automatically partitioning it from web apps.
We’ve seen how Logic Bank can reduce over 95% of backend effort by 40X, with extensibility, scalability and manageability. If you are using SQLAlchemy, it’s worth checking out.
But it’s more than that. This level of advantage can influence your technology stack decision. You may already be considering Python for its productivity, simplicity and popularity. Coupled with declarative business logic, the question may really be whether you can afford not to check it out.
Logic Bank is open source, here. If you’re new to Python, there are also instructions on how to install it for Windows and Mac.
Topics: DATABASE ACCESS, BUSINESS LOGIC, AGILE ARCHITECTURE, DATABASE, TUTORIAL
Opinions expressed by DZone contributors are their own.
ABOUT US
ADVERTISE
CONTRIBUTE ON DZONE
LEGAL
CONTACT US
Let’s be friends:
DZone.com is powered by
#database #tutorial #business logic #database access #agile architecture