Shifts in coding paradigms

Last modified
Saturday, August 21, 2021 - 14:44

LedgerSMB's code base has a relatively long history, given that it's web-software, with the first release happening as SQL-Ledger in 1999. A lot has happened since 1999 in the world of web software and as a consequence, so did the approach to developing LedgerSMB itself.

This shows when working with the code base. This page summarizes the different approaches taken during the life-time of the LedgerSMB code base, to help work with the various types of code.

1.0/1.1/1.2 (a.k.a. "old code")

These versions inherit their style of web development mostly from SQL Ledger. Response HTML documents are being generated by a mix of processing logic and string literals, which get spliced with (string) variable values as a surrogate for templates.

This code makes minimal use of packages and lots of global variables. Code from this era has been put into the 'lsmb_legacy' package in 1.3+.

1.3 (a.k.a. "new code")

In 1.3, a number of significant changes have been implemented:

  • All code is in "its own" package
  • Minimal global state
  • Separation of code and data, using templates
    • Response pages based on templates
      with template processing outsourced to Template Toolkit
  • Separate layers for handling
    • the request
    • the database interaction
    • template processing

In other words, LedgerSMB 1.3 code looks a lot more like today's applications do.

1.4 (yet-even newer code?)

While all versions before 1.4 used mostly static HTML pages, with 1.4 a step was made to make the application more interactive without constant page-reloading by replacing the Scriptaculous JavaScript library with the Dojo toolkit JavaScript web application framework.

Additionally, abstractions have been created which allow quick development of reports, by implementing minimal infrastructure: a stored procedure and a filter page which specifies search parameters. Sometimes a LedgerSMB::Report class also needs to be implemented, but many times the standard class is good enough.

On the class definition side, the switch has been made to the Perl "Moose" object system which allows declarative class specifications, with typed slots. Classes converted to Moose perform input validation upon class instantiation.

1.5 (yet-even newer new-code?)

Changes in 1.5:

  • All response documents converted to Dojo-compatible output
  • Database mapper (DBObject) factored out and published as its own project (PGObject)
  • Frameless (i.e. single-page!) JavaScript client-side user interface
  • Asynchronous request processing

As a consequence of the above, it's now possible to submit a request and wait for the result before taking action. A notable example is that in the past, a submitted form with data-entry errors would be replaced by a page pointing out the errors of the user's ways. In 1.5, a popup will tell the user about the errrors with the data entry in the background -- ready to be corrected.

In general, with the move to full-Dojo application, the ability to provide the user with near-immediate feedback has been introduced.


All "new code" entry points have been switched to return a PSGI triplet (http status code, headers arrayref, body arrayref or file handle).

Additionally, centralized functionality has been established to call into "old code" from "new code" through the lib/LedgerSMB/ module. "Calling" into old code used to happen in-place for versions 1.3 through 1.5.

This release switches from our own framework for database tests to pgTAP: a framework for SQL testing which integrates with Perl's testing facility prove.


All transaction lines have their own foreign currency exchange rate associated to ensure maximum flexibility in support of different use-cases.


All authentication code has moved to middleware modules.


JavaScript code is now "transpiled" using webpack. Prior releases used Dojo's own minimization approach. webpack has a much wider range of tools available to help manage the JS part of the code base.