How is it RAD?

RAD standards for Rapid Application Development, so to be classed as "rapid" a framework should be able to assist the developer in creating application components as rapidly as possible, and preferably at a faster rate than any rival frameworks. In my experience the speed at which developers can create new components is directly proportional to the amount of reusable code which is at their disposal. The idea is that the more reusable code you have at your disposal then the less code you will have to write and maintain. The less code you have to write to get the job done then the quicker you can get it done and the more productive you will be.

An enterprise application will typically contain hundreds if not thousands of separate components known as User Transactions. While each of these transactions may involve executing a large amount of program code, it is simply not economical to duplicate every line of code for every transaction. When writing software it is good practice to spot where logic is duplicated and to move that logic into some type of reusable module so that it can be defined once and then referenced multiple times. This reusable module may be one of the following:

  • A function within a library which can be called from many places.
  • An abstract class which can be inherited by multiple concrete classes.
  • Some sort of template which provides a standard structure which can be filled in with details at run time.

The real measure of a good programmer is his ability to spot repeating patterns in code. While it is easy to spot where entire segments of identical code have been duplicated what is less easy is where there are similarities mixed with slight differences. This then requires the ability to separate out the similar from the different, the abstract from the concrete, so that the similar can be placed in a reusable module and the different can be placed in unique modules. This leads to a technique known as programming-by-difference so that after you have spent some time in creating a reusable module to contain the similar you can concentrate all your remaining time on dealing with the differences.

So how much code can be converted into reusable modules? Program code can be roughly split into two categories:

  • Business logic - this is the heart of the application as far as the end user is concerned.
  • Non-Business logic - this is sometimes referred to as boilerplate code or glue code which deals with common things such as user interface code and database code. This is the code that allows the relevant business rules to be processed at the relevant time on the relevant data.

In the RADICORE framework 100% of the non-business logic is supplied by the framework. This means that each developer can spend 100% of his time on the business logic.

The first step in providing reusable components is to use an architecture which is comprised of modules which fall into one of these two categories, as shown in the following structure diagram:

3-Tier Architecture combined with Model-View-Controller

model-view-controller-03a (5K)
  • All requests from the user are received by a Controller module in the Presentation layer (User Interface or UI). This request is then converted into one or more method calls on one or more Models. When the Models have finished the Controller will activate the View component in order to return the response to the user.
  • When a module in the Business/Domain layer, which is known as a Model, is activated it will perform a series of standard operations on its database table. These operations can be a mixture of Create, Read, Update and Delete (CRUD) which apply to every database table regardless of it structure and contents.
  • If any communication with the physical database is required this is handed off to a separate Data Access Object (DAO) where the SQL query is assembled and executed. Note that there is a separate DAO for each vendor's database, such as MySQL, PostgreSQL, Oracle and SQL Server, as each one has its own API calls.
  • When the View is activated it will extract all the application data from the Model and transform it from a native PHP array into some other format. This will usually be HTML, CSV (for spreadsheets), or PDF (for printable documents). Note that some Controllers do not produce a View.

During the experience I gained while building hundreds of transactions for numerous systems in other languages I observed a number of different patterns which appeared numerous times. It was quite common, having built a transaction for one database table, that the same processing was required on a different database table. This meant that the logic was the same and could potentially be shared, with the only difference being the data. This enabled me to construct a library of reusable Transaction Patterns. All I needed to do was find a simple way of linking a pattern with a database table to generate a combination which was runnable. Fortunately I found a way of utilising the three pillars of OOP - namely encapsulation, inheritance and polymorphism - to engineer a solution.

Virtually every transaction in every subsystem is comprised of a different collection of the above four modules, so I engineered a way to provide each of these modules with as much reusable code as possible:

  • Models - a separate Model is required for each database table as each table represents a separate packet of data with its own business rules. Some of these rules are buried within the table's structure, so I found a way, using a Data Dictionary of my own design, to extract a table's structure from the database and import it into that table's class file. Where I found segments of non-business logic which could be shared by multiple table classes, such as primary data validation, I moved that code into an abstract table class which could then be shared by inheritance. When I later discovered the need to insert custom business logic into a table class my use of an abstract class enabled me to employ the Template Method Pattern and place this business logic into "hook" methods.
  • Controllers - there is a separate pre-built Controller for each of the 45 Transaction Patterns. These control which methods are called on the Model(s) and although the names of these methods are hard-coded the identity of the Model is not known until run time. This information is provided in a separate component script.
  • Views - These present a response (if there is one) to each request in order to convert the application data within each Model from a native PHP array into a format which the user can read and understand. It is usually an HTML document, but it may be a CSV or PDF document. There is a single reusable component for each format, so there is nothing that a developer need build.
  • DAOs - The rules for building SQL queries are the same regardless of what information is held in each table, so this logic can be supplied in a single component which can then produce queries for any table. The only reason to have a separate version for each database vendor is that they have separate API calls which cannot be shared.

All of these modules supply 100% of the boilerplate code. The only place where developers need to insert their own custom business logic is in the "hook" methods within each concrete table class. All non-business logic is inherited from the abstract table class.