Why I don’t do Domain Driven Design

- dict_table.class.inc – for standard processing
- dict_table_s01.class.inc – to import table names into the Data Dictionary database.
- dict_table_s02.class.inc – to export table data to a PHP script.
- dict_table_s03.class.inc – to display list of Transaction Patterns.
- dict_table_s04.class.inc – to generate the scripts and update the MENU database for the selected Pattern.
Separate Controllers for each use case
In my early days as a developer when I was working with COBOL it was common practice to create a program called “Maintain XXX” where “XXX” was a particular entity (table) which was of interest to the business. This could handle all the CRUD operations which could be performed on that entity, so it needed a mechanism to switch from one operation to another. A typical set of operations was List, Create/Add, Read/Enquire, Update and Delete where each had its own screen and its own business logic. The difference between “List” and “Read” is that “List” can display multiple rows on the screen whereas “Read” (and all the others) can only deal with one row at a time. We called each of there operations a “mode” and had function keys (with labels) on the each screen so the user could switch from one mode to another. The program would always start in “List” mode, and the functions for the other modes were always available.
This practice was continued until the mid-1980s when a customer came up with the requirement for access to individual modes to be denied to certain users, and for the function labels to disappear when access was denied. This had be configurable on the database rather than in code so that it could be modified more easily. Creating a new database table, then modifying the code to act upon the contents of this table proved to be rather tricky, so after a while I decided that the best solution would be to break apart each multi-mode/multi-screen program and create a separate sub-program for each mode. This meant that instead of a large complex program I ended up with a collection of smaller but simpler subprograms each of which dealt with a single mode and a single screen. This resulted in the structure shown in Figure 2 below:
In this collection, which I now call a “family” because of the parent-child relationships, The LIST1 form is usually activated from a menu button, although the LIST2 variant is usually activated from a navigation button. All the child forms are activated from navigation buttons. This means that the user has to go through the parent form in order to get to a child form. The advantage of having all the members of this family being separate tasks (user transactions) with their own entries on the TASK table is that their positions in any menu bar or navigation bar is not hard-coded, it is completely dynamic. The features of the Role Based Access Control (RBAC) system which is built into the framework means that access to individual members of the form family can be turned ON or OFF at will without the need for any code changes.
An additional advantage of having a separate component for each member of the forms family, coupled with the fact that each Model (table) class shares the same set of common table methods, thus providing polymorphism, is that once a Controller has been built to perform a series of method calls on its table class(es) it can be made to call exactly the same methods on a different table class through that mechanism known as dependency injection. This mechanism means that each Controller script can be used with any table class.
It should also be noted that in aggregate compositions I do not have a single class for the aggregate to handle all the use cases for that aggregate. No matter how many tables are in that aggregate all I see are a number of pairs of tables which are joined in a parent-child relationship, and each pair is dealt with using its own family of forms.
Please also refer to Transaction (use case) similarities and Transaction (use case) differences.
More Reusability = Higher Productivity
Before I started using the OO capabilities of PHP I asked myself “why I should bother? What’s so great about OOP?” I found the answer in the following statement:
Object Oriented Programming involves programming which is oriented around objects, thus taking advantage of Encapsulation, Inheritance and Polymorphism to increase code reuse and decrease code maintenance.
This rang a bell with me as the frameworks which I had developed in my two previous languages had helped increase the productivity of the whole development team by replacing the need to write chunks of identical or similar code with pre-written and reusable code. The less code you have to write to get the job done then the less time it takes to get the job done and the more productive you can be. I therefore set out to use these features of PHP to increase as much as possible the amount of reusable code I could have at my disposal.
While using a layered architecture is a step in the right direction, it is how you construct each of the different components in that architecture which indicates if you are taking proper advantage of the features which OOP has to offer. By following my own version of “best practices”, and ignoring those which have a dubious pedigree, I have been able to provide the following amounts of reusability which help reduce development times and increase my rate of productivity:
| Models | Each table class inherits all its standard code from a single abstract table class while any non-standard code can be inserted into the available “hook” methods. |
| Views | There is a single reusable component for each type of View:
|
| Controllers | Each of the reusable Controllers calls a predetermined series of methods on an unknown Model (or Models) where the identity of those Model(s) is passed down at run time from a component script. There is a separate version of this script for each user transaction (use case). Each Controller is paired with no more than one View, as documented in Transaction Patterns, but there are some which have no View at all. |
| DAOs | Each of the reusable Data Access Objects generates the queries for the common CRUD operations for a particular DBMS. Each method will build its query based on the information passed to it by the Model, then call the API which is specific to that DBMS. |
You should notice here that every Model class supports the same set of methods as every other Model class, and every Controller communicates with its Model(s) using those methods. This is a prime example of polymorphism, and it allows any Model to be used with any Controller.
You should also notice that as much standard code (often referred to as boilerplate code) as possible is supplied by the framework, which means that the bulk of the developer’s time can be spent on the important code which deals with the business rules.
While DDD contains many principles and practices, I regard these as “suggestions” and not “rules”, which means that I am free to either follow them, in whole or in part, or ignore them altogether. Where I find a simpler way to achieve an objective then I will follow the KISS principle and ignore the KICK alternative.
While some of these topics are not explicitly mentioned as being part of DDD I have included them because they are part of the OO family of practices and therefore may be implied.
Associations
When I first encountered the term association in various newsgroup postings all I saw was a complicated way of dealing with relationships. It does not matter to me how many tables are linked together in a hierarchy, that hierarchy is nothing more than a collections of tables where different pairs of tables are linked together in a parent-child relationship, and each relationship can be dealt with by standard code in the framework and not custom code in any table class.
You can read more of my thoughts on this topic in Object Associations are EVIL.
Aggregates
OO afficionados like to use the “HAS-A” test to help them recognise things called “object compositions”. The wikipedia article contains the following description:
Has-a is a composition relationship where one object (often called the constituted object, or part/constituent/member object) “belongs to” (is part or member of) another object (called the composite type), and behaves according to the rules of ownership. In simple words, has-a relationship in an object is called a member field of an object. Multiple has-a relationships will combine to form a possessive hierarchy.
An Aggregation implies that the contained class can exist independently of the container. If the container is destroyed, the child is not destroyed as it can exist independently of the parent.
It does not matter to me how many objects are linked together in some sort of hierarchy, at the end of the day it is just a collection of tables which are arranged in a number of one-to-many/parent-child relations, and in the RADICORE framework there are standard patterns for dealing with parent-child relationships which do not require any custom code in any table class.
I have written more on this topic in Object Associations – Aggregations and A single class for an Aggregation is a mistake.
Compositions
A Composition is a type of aggregation in which the contained class cannot exist independently of the container. If the container is destroyed, the child is also destroyed.
I have written more on this topic in Object Associations – Compositions.
There is a different type of composition which is supposed to be an alternative to inheritance which I have written about in Composition is a Procedural Technique for Code Reuse.
Class hierarchies
I have seen where more than a few developers use the “IS-A” test to identify the existence of class hierarchies. They make statements such as “a CAR is-a VEHICLE”, “a BEAGLE is-a DOG” and “a CUSTOMER is-a PERSON”, and this causes some developers to ask the question:
If object ‘B’ is a type of object ‘A’, then surely ‘B’ must be a subclass of ‘A’?
This can lead to statements such as: A Car and a Train and a Truck can all inherit behavior from a Vehicle object, adding their subtle differences. A Firetruck can inherit from the Truck object, and so on.
which would produce hierarchies of classes which are multiple levels deep.
This is not how it is handled in a database, so it is not how it should be handled in the code.
Expanding on the “a BEAGLE is-a DOG” statement from above someone who has been trained to think in the “object oriented way” would identify dog_type as the differentiator and create a separate subclass for each possible value, as shown in Using “IS-A” to identify class hierarchies.
If dog_type is identified as the differentiator then it should become a column on the DOG table which can be used as the foreign key to an entry on the DOG_TYPE table. In this way it is possible to introduce as many different types of dog that you can think of without having to create a separate class for each.
In database applications every entity in the Business/Domain layer IS-A database table, and because every table shares the same CRUD operations every table class shares the same table methods which are inherited from the same abstract table class. This means that I do not have any deep inheritance hierarchies, with the only exception being when I need subclasses to deal with different implementations for the standard “hook” methods.
CQRS
This is what it says in the wikipedia page:
Command Query Responsibility Segregation (CQRS) is an architectural pattern for separating reading data (a ‘query’) from writing to data (a ‘command’). CQRS derives from Command and Query Separation (CQS), coined by Bertrand Meyer.Commands mutate state and are approximately equivalent to method invocation on aggregate roots or entities. Queries read state but do not mutate it.
This is the description for Command Query Responsibility Segregation (CQRS):
In information technology, Command Query Responsibility Segregation (CQRS) is a system architecture that extends the idea behind command-query separation to the level of services. Such a system will have separate interfaces to send queries and to send commands. As in CQS, fulfilling a query request will only retrieve data and will not modify the state of the system (with some exceptions like logging access), while fulfilling a command request will modify the state of the system.Many systems push the segregation to the data models used by the system. The models used to process queries are usually called read models and the models used to process commands write models.
The idea that I should have one model for reading and another Model for writing is unacceptable to me. As far as I am concerned this violates the principle of encapsulation which states that ALL the methods and ALL the properties for an entity should be maintained in the SAME class. This means that you do not split those methods and properties across multiple classes, nor do you put methods and properties for multiple entities in the same class.
In a database application each entity in the Business layer IS-A database table, and the only operations which can be performed on a database table are Create, Read, Update and Delete (CRUD). This is why I created a set of methods to perform these operations, and because they are common to every table I make them available in every table class by inheriting them from an abstract class.
Factories
In this paper Domain-Driven Design Reference Eric Evans wrote the following:
When creation of an entire, internally consistent aggregate, or a large value object, becomes complicated or reveals too much of the internal structure, factories provide encapsulation.
I do not use object aggregations, therefore I do not need any factories.
I do not need a method of creating objects with different configurations as each of my table objects has only one possible configuration, and that is dealt with in the class constructor.
Getters and Setters
While learning how PHP worked I saw that it was common practice to create classes with separate properties for each table column, and to access them using separate getters and setters. I did not like this idea as it would mean that each table (Model) class would require its own set of properties with their getters and setters and that each of these classes would then require its own Controller with the necessary code to access these unique properties. This would therefore make each Controller tightly coupled to a particular Model and throw out of the window any opportunity of having reusable code. I had already noticed that data being sent in from an HTML form was presented in an associative array, and that data read from the database was also presented in an associative array (actually an indexed array of associative arrays), so I decided not to unpick this array into its components parts but to pass it around in its array form as a single argument on every method call. This is shown in the common table methods as the $fieldarray argument. This simple idea provided several benefits:
- As neither the Model nor the Controller required individual table columns to be defined it meant less code to write.
- As the Controller did not have to contain any references to any columns in its Model it then made them loosely coupled which meant that any Controller could use any Model.
- Because none of the method calls between the Controller and the Model reference any column names it meant that I could change the columns on any table without having to change any method signatures, thus avoiding the ripple effect.
Note that each table class “knows” what columns belong in its table as they are list in the $fieldspec array.
Interfaces
By “interfaces” I mean object interfaces which require the use of those keywords interface and implements. These did not exist in PHP4 so I could not use them. They were introduced in PHP5, but after reading their description in the manual I decided that as I was already using an abstract class to great affect I had no need for them.
I later discovered that they were added to other languages to provide a way of allowing polymorphism without inheritance in certain strictly typed languages. They were added to PHP just because some not-so-bright programmers said Other OO languages support interfaces, so PHP should support them as well.
This is a ridiculous argument as PHP is not strictly typed, nor does it require any mechanism to support polymorphism other than several classes containing the same method signatures. This means that they are totally redundant in PHP and a complete waste of time as they serve no useful purpose.
This topic is covered in more detail in Object Interfaces are EVIL.
Method names
I have seen many examples where method names are constructed to reflect an action which has been identified in the design process, such as “createCustomer”, “SignUpForMagazineSubscription”, “accept offer” and “withdraw”, but I never followed this practice. My aim of switching to an OO language was to use the facilities offered by encapsulation, inheritance and polymorphism to create as much reusable code as possible. I therefore creating my own convention for naming methods.
I also knew two things from my previous experience:
This means that names such as “createCustomer”, “SignUpForMagazineSubscription”, “accept offer” and “withdraw” I consider to be nothing more than labels which may be beneficial to the user but which are irrelevant details in the software. By stripping away the irrelevant and concentrating on the essential I make it easy for the developer to quickly understand the effects of each user transaction and to identify the components that will produce that effect. The labels made available to users are nothing more than names held on the TASK table in the MENU database.
| OO purists | effect on the database | the Tony Marston way |
|---|---|---|
| createProduct($_POST) | insert a record into the PRODUCT table |
$table_id = 'product'; .... require "classes/$table_id.class.inc"; $dbobject = new $table_id; $result = $dbobject->insertRecord($_POST);
|
| createCustomer($_POST) | insert a record into the CUSTOMER table |
$table_id = 'customer'; .... require "classes/$table_id.class.inc"; $dbobject = new $table_id; $result = $dbobject->insertRecord($_POST);
|
| createInvoice($_POST) | insert a record into the INVOICE table |
$table_id = 'invoice'; .... require "classes/$table_id.class.inc"; $dbobject = new $table_id; $result = $dbobject->insertRecord($_POST);
|
| payInvoice($_POST) | insert a record into the PAYMENT table |
$table_id = 'payment'; .... require "classes/$table_id.class.inc"; $dbobject = new $table_id; $result = $dbobject->insertRecord($_POST);
|
In my method the value for $table_id is provided in a component script and this is instantiated into an object in the controller script.
The use of an abstract class also provides the means to have methods for standard processing interspersed with methods for custom business rules. This is called the Template Method Pattern and involves a mixture of invariant/fixed methods and variable/customisable or “hook” methods which can have different implementations in different concrete classes. Every public method in the abstract table class is an example of a Template Method.
Repositories
In this paper Domain-Driven Design Reference Eric Evans wrote the following:
Query access to aggregates expressed in the ubiquitous language. Proliferation of traversable associations used only for finding things muddles the model. In mature models, queries often express domain concepts. Yet queries can cause problems. The sheer technical complexity of applying most database access infrastructure quickly swamps the client code, which leads developers to dumb-down the domain layer, which makes the model irrelevant.
I do not deal with aggregates in the DDD way.
Abstraction is a process whereby you separate the abstract from the concrete, the similar from the different, with the aim of putting the similar into a reusable object and the different into unique objects. This section identifies what I recognise as “different” and how I have isolated them from the “similar”.
Entity/Table differences
While each database can contain any number of tables each one will have its differences which can be categorised under the following headings:
- Database name.
- Table name, which must be unique within the database.
- A list of columns, where each has:
- A name which must be unique within that table.
- A data type (character, integer, float, date, time, etc.
- An optional size.
- A primary key, which may contain one or more columns.
- Zero or more candidate keys, where each may contain one or more columns.
- A list of one-to-many/parent-child relationships with other tables:
- A list of child relationships where this table is the parent.
- A list of parent relationships where this table is the child.
- Column values which can vary depending on the table and the operation being performed. Instead of having a separately named class property for each column I prefer to use a single array variable as it promotes loose coupling which is better than tight coupling.
These have been implemented as a set of common table properties which are inherited from an abstract table class. Each of these properties will be loaded in when the class file is instantiated into an object.
HTML differences
Having abstracted out all the similarities in every HTML document I am left with the differences. While the XSL Stylesheet contains the necessary instructions to construct all the standard elements on the HTML page I am left with the one variable which is the zone which handles the application data. This is where I have to identify which piece of table data goes where in that zone. Because I have to copy all the necessary framework and application data to an XML document I discovered, after a bit of experimentation, that I could also include a description of this application zone in this XML. This meant that instead of having a separate version of an XSL stylesheet for each different screen I could use a standard stylesheet and load data from an external screen structure file like the one shown below:
// this identifies which XSL stylesheet to use $structure['xsl_file'] = 'std.detail1.xsl'; $structure['tables']['main'] = 'person'; $structure['main']['columns'][] = array('width' => 150); $structure['main']['columns'][] = array('width' => '*'); $structure['main']['columns'][] = array('class' => 'classname'); $structure['main']['fields'][] = array('person_id' => 'ID'); $structure['main']['fields'][] = array('first_name' => 'First Name'); $structure['main']['fields'][] = array('last_name' => 'Last Name'); $structure['main']['fields'][] = array('initials' => 'Initials'); $structure['main']['fields'][] = array('nat_ins_no' => 'Nat. Ins. No.'); $structure['main']['fields'][] = array('pers_type_id' => 'Person Type'); $structure['main']['fields'][] = array('star_sign' => 'Star Sign'); $structure['main']['fields'][] = array('email_addr' => 'E-mail'); $structure['main']['fields'][] = array('value1' => 'Value 1'); $structure['main']['fields'][] = array('value2' => 'Value 2'); $structure['main']['fields'][] = array('start_date' => 'Start Date'); $structure['main']['fields'][] = array('end_date' => 'End Date'); $structure['main']['fields'][] = array('selected' => 'Selected'); ?>
Note that for input and update screens I will need to include for each application column the identity of the HTML control (textbox, radiogroup, dropdown, checkbox, etc) which should be used. This information is obtained from the $fieldspec array which has been loaded into the object’s memory from the table structure file.
Transaction (use case) differences
As explained in Transaction (use case) similarities each user transaction (use case) will require a Model, a View and a Controller to act in unison to carry out the task required by the user.
While each subsystem will require its own set of user transactions (use cases) these can be generated by the framework by linking a table class with any of the Transaction Patterns which are supplied by the framework. Each user transaction which then have its own component script in the file system which looks like the following:
$table_id = "person"; $screen = 'person.detail.screen.inc'; require 'std.enquire1.inc'; ?>
As you can see this is a simple script whose purpose is to identify the following:
$table_ididentifies the Model part of MVC. This is one of the generated database table classes.$screenidentifies the View part of MVC. This is one of the generated screen structure scripts which identifies the HTML differences.includeidentifies the Controller part of MVC. This is one of the pre-written controller scripts.
Each Controller is designed to work with only a single View, but a small number of Controllers do not have a View at all. For a complete list of the available Controllers and the Views which they support please refer to Transaction Patterns for web applications.
Note that each Controller can work with any Model, but it does not know which one until it is given a value for $table_id at run-time. It also means that each Model can work with any Controller.
Use these links for the validation similarities and validation differences.
Validation differences
While the similarities can be handled by a standard component within the framework it is often necessary for a particular operation on a particular table to be interrupted at a particular point in order to execute some custom code, either for some non-standard data validation or to apply a particular business rule. This can be done in the RADICORE framework by locating the relevant customisable method which has been been into the processing flow for that operation, then copying that empty method into the subclass so that it can be filled with the necessary code. Various methods are available, such as:
There are also other customisable methods with names such as the following:
Note that these customisable methods are available because of my implementation of the Template Method Pattern which was made possible because of my decision for all concrete table classes to inherit from an abstract table class.
Abstraction is a process whereby you separate the abstract from the concrete, the similar from the different, with the aim of putting the similar into a reusable object and the different into unique objects. This section identifies what I recognise as “similar” and how I have turned them into reusable components.
Entity/Table similarities
Although each database table holds different data they are all subject to exactly the same set of operations which are Create, Read, Update and Delete (CRUD). These have been implemented as a set of common table methods which are inherited from an abstract table class. Instead of having separate methods for load(), validate() and store() I have grouped them together into wrapper methods as they always have to be called in the same sequence, and it is more efficient to write a single call to a wrapper method instead of a number of calls to the low-level methods. It also makes it easier to modify the contents of a wrapper method without having to modify any code which calls that method.
The advantage of being able to inherit these methods from an abstract class is that they do not have to be defined in each concrete class as they are automatically there when the class is instantiated into an object. This is why each table class file can be generated from the same template, as shown below:
require_once 'std.table.class.inc';
class #tablename# extends Default_Table
{
function __construct ()
{
$this->dirname = dirname(__file__);
$this->dbname = '#dbname#';
$this->tablename = '#tablename#';
$this->fieldspec = $this->loadFieldSpec();
}
}
?>
The loadFieldSpec() method is responsible for transferring the contents of the table structure file into the object’s common table properties which configures the object with all the knowledge it requires so that it can deal effectively with that particular table.
Note that the table class file, when it is first created, does not contain any methods other than the constructor as all the standard processing is performed by the common table methods which are inherited from the abstract table class. The use of an abstract class enables the Template Method Pattern to be implemented. This involves the use of invariant/fixed methods to be defined in the superclass which can be interspersed with variable/customisable “hook” methods which can be overridden within each subclass to provide custom behaviour.
SQL query similarities
Communicating with a relational database is very straightforward. It is a simple matter of constructing an SQL query, which is a string of text, and sending to the database using the relevant function. There are only four basic methods for manipulating data, part of the Data Manipulation Language (DML), and they are:
The query string which is constructed for each of these operations/methods follows the same pattern regardless of what data is being processed.
| Operation | Code |
|---|---|
| Create |
INSERT INTO
|
| Read |
simple: SELECT * FROM
|
| Update |
UPDATE
|
| Delete |
DELETE FROM
|
Note that the Create, Update and Delete operations function on only one table at a time whereas the Read operation can obtain data from several tables.
As you should see the table names, column names and column values are nothing more than pieces of text which appear in the query string along with various keywords, so none of these names have to be specified in separate arguments on the function call to the DBMS. As PHP has excellent string handling functions I found it very easy to create a single Data Access Object (DAO) which can handle the generation and execution of any query for any table in any database. Each of the four methods – one for each of the above operations – is fairly basic as it responds to the instruction “take this data and construct and execute an SQL query for the DBMS”. All I have is a separate DAO class for each supported DBMS (MySQL, PostgreSQL, Oracle and SQL Server) as the query strings may be similar but the function calls are not.
I have seen other people’s implementations where they have a separate DAO for each table, but my method is far easier as I can add, remove or modify tables at will without having to add, remove or modify any DAOs.
HTML similarities
Unlike in my previous languages where each screen had to be built using a special tool and then compiled, I knew that each web page was nothing more than a text file, with a mixture of tags and values, that had to be constructed from scratch before it could be sent to the client device. I also knew that I did not want to follow the examples I encountered in various books and online tutorials and build each HTML document by spitting out little fragments one piece at a time during the execution of each script.
Because in my previous languages I had built hundreds of different screens for dozens of different applications I had already begun to spot a number of similarities between them. While each screen had different values they each had a structure that was common to other screens, so I looked for a way to hold each different structure in some sort of template so that at run time all I needed to do was fill that template with values. I did not bother searching for templating systems as I had already encountered XML and XSL Transformations in UNIFACE. I played with these on my home computer and discovered that I could easily transform XML into HTML, so after confirming that PHP had the ability to create XML documents from SQL data and perform XSL Transformations, I decided to build all my web pages in this way.
For this I built a standard service object which took as its input one or more entities from the Business/Domain layer and the identity of an XSL stylesheet. Its function was to copy each entity’s data into the XML document, add various framework data into that document, load the nominated XSL stylesheet into memory, then perform the XSL transformation. The output from this process was then sent to the client device. In my initial version, which is described in Generating dynamic web pages using XSL and XML, I had a separate XSL stylesheet for each screen as I had to specify which piece of data went where. After some experimentation and refactoring I found a way to replace these custom-built XSL stylesheets with a smaller collection of Reusable XSL Stylesheets and Templates which make use of a separate screen structure file to identify which piece of application data goes where.
The areas of each web page which area common and can be supplied by the framework without any intervention by the developer are as follows:
Each screen has its own Data area which is supplied by each table class.
I had observed earlier that after building a user transaction which did something to a particular database table that I often needed to produce another transaction which did the same thing to a different table. On closer examination I was able to split each transaction into three categories – structure, behaviour and content – where the structure and behaviour were the same with just the content being different. I first documented this idea from my experience with Component Templates in UNIFACE which, for my PHP implementation, I later updated to What are Transaction Patterns? This collection of patterns works as follows:
Note that each screen structure is documented in the RADICORE library of Transaction Patterns for web applications where it is coupled with a reusable Controller script to provide a standard pattern for user transactions (use cases). Note that any Controller script can be used with any Model (table) class as they all use the same set of common table methods. This provides vast amounts of polymorphism which is a vital ingredient of Dependency Injection.
Transaction (use case) similarities
Note that when I use the word “transaction” I mean “user transaction” or “business transaction” (to differentiate from a database transaction) which is also known as use case or unit of work. In the RADICORE framework I also use the name “task” (because it’s nice and short) as details of each task are stored in the framework’s TASK table.
Using the structure shown in Figure 1 it follows that every task in the system will need one component from each of those component types, and each of these components will be provided from different sources as follows:
Note that it does not matter how much data is submitted on the HTML form or what the column/field names are, it is all made available in the $_POST variable which is an associative array. In order to remove the need for code to deconstruct this array and feed in the data one piece at a time, which would automatically produce tight coupling, I leave this array intact as pass it around as a standard $fieldarray argument on all method calls, as shown in common table methods.
Note that a particular Controller scripts and a particular View are paired together to form a Transaction Pattern.
The identity of each of these components is documented in the Transaction (use case) differences.
Each of these user transactions (tasks) will require entries in the framework’s MENU database as follows:
- An entry on the TASK table to provide a user-friendly title and other settings.
- An entry on the MENU table if it is to appear in the Menu bar.
- An entry on the NAVIGATION_BUTTON table if it is to appear in the Navigation bar for a parent task.
- An entry on the ROLE_TASK table to grant access to this task to user with this ROLE.
Each user of the system will require the following entries in the framework’s MENU database:
- An entry on the USER table to identity each person who is authorised to access the system.
- One or more entries on the USER_ROLE table to identify the different ROLES that the user may have.
It is only necessary to construct one set of Menus and Navigation buttons as it is a function of the Role Based Access Control (RBAC) software which is built into the framework to filter out any task to which the user does not have access. If the user cannot see a button to activate the task then it cannot be activated.
Use these links for the similarities and differences in the validation and business rules.
Validation similarities
There is one universal rule that every developer SHOULD follow when writing software which takes input from a user and adds it to the database and that is to check that each piece of data is compatible with its column specifications BEFORE it is sent to the database otherwise the query will not execute and the software will come to a grinding halt. The correct behaviour is to check each column’s value against its specifications, and if this check fails in any way it should be sent back to the user with a suitable error message so that the mistake can be corrected so that the operation can be tried again.
Because this is a universal requirement it should be possible to perform this checking in a standard component. This can be done within the RADICORE framework because of two simple design decisions:
- I do not have a separate class property for each column’s data. Instead I pass all the data into and out of each table’s object as an associative array. This is to take advantage of the fact that data sent in from an HTML form is presented in the $_POST array, and data retrieved from the database using the
_fetch_assoc() method will also be returned as an associative array. - Each column’s specifications are available in the $fieldspec array.
Note that the use of separate class properties for each column leads to tight coupling (which is bad) whereas a single array property leads to loose coupling (which is good)
The existence of these two arrays then makes it a simple process to write a standard validation object which can compare the contents of the two arrays to verify that each column’s value matches its specifications.
I have designed and built numerous enterprise applications from scratch using totally different languages over several decades, so I have more than a passing knowledge of the steps which are required to undertake such a task. The iterative Gather-Analyse-Design cycle is always the same, it is only the results of those iterations, the database design, the business rules, and the tasks required to maintain the contents of that database which are different. The deciding factors for a successful implementation are always the same – the accuracy of the design closely followed by the ability of the development team to implement this design using the tools at their disposal. These tools will include the programming language, the DBMS, the code editor, the debugger, and the framework. If any of these is not up to par – either the design, the developers or the development tools – then the result will also not be up to par.
An experienced developer should realise that, despite the differences in the databases, every table is subject to exactly the same operations and can therefore be handled in the same way. Despite the differences in the business rules they can all be handled in the same way. Because these differences can be handled in similar ways it should be possible to reduce these patterns of similarities into reusable code.
I have encountered numerous formalised design methodologies over the years, but neither I nor my fellow developers could ever be persuaded to commit ourselves 100% to a single methodology. We have always chosen the pick-and-mix approach whereby we picked the parts that we liked, ignored the parts that we didn’t like, and mixed them together in a way that suited us. I particularly dislike those parts of DDD which are biased towards the way that OO thinkers are taught to build their solutions, such as associations, aggregations, compositions, factories and repositories. Those are implementation details and should have no effect on the design process.
A large Enterprise Application often has to cover a collection of different business areas, but it would be wrong to think of each of these areas as a separate domain as they have their similarities as well as their differences. It is precisely because of the volume of similarities that I think of this collection of business areas to be a complete system while each member of this collection is just a subsystem. The domain/system is therefore a database application while each subdomain/subsystem is just an implementation of that domain which deals with its particular differences.
I designed and built the RADICORE framework specifically to deal with the domain of database application, which means that it has standard ways of dealing with database tables and their relationships, and each subsystem/subdomain can deal with its own set of tables and relationships using these standard ways. The framework also has standard ways of generating HTML pages, CSV files and PDF reports. Once the database has been designed and built the framework’s Data Dictionary can be used to generate both the table classes and, using its library of Transaction Patterns, the user transactions necessary to maintain the contents of those tables. While each of these transactions can be run immediately from the framework’s system of menus they do not contain any business rules, but the developer can add these later by inserting the necessary code into the “hook” methods which are available in every table’s class. Each subsystem is therefore generated by the framework as an add-on and run from the framework as just another part of an integrated system.
The current RADICORE framework is actually the third iteration of a framework which I first developed in the mid-1980s in COBOL and in the 1990s in UNIFACE, and each iteration has improved my levels of productivity. For example, the time taken to implement this family of forms for a single database table has been reduced as follows:
- In COBOL it would take 5 (five) days.
- In UNIFACE it would take 1 (one) day.
- In PHP it takes 5 (five) minutes. (yes, I did write MINUTES and not DAYS).
No matter what the OO afficionados say I ALWAYS start writing code AFTER I have designed and constructed a properly normalised database, then I use RADICORE’s code generation facilities to construct the basic components which I then season to taste. When I came to build the TRANSIX application in 2007, my first ERP package I started with some comprehensive database designs which I found in Len Silverston’s Data Model Resource Book. These database were PARTY, PRODUCT, ORDER, INVOICE, INVENTORY and SHIPMENTS. I built the components, added the business rules, and demonstrated the first working version to a customer after just 6 man-months. That is an average of one man-month per database. If I were to change my methods and follow the “advice” given by these pseudo-experts and their so-called “best practices” then my levels of productivity would plummet like a lead balloon, so excuse me if I don’t follow the crowd and become a Cargo Cult Programmer like so many others in the programming community.
Here endeth the lesson. Don’t applaud, just throw money.
The following articles describe aspects of my framework:
The following articles express my heretical views on the topic of OOP:
These are reasons why I consider some ideas on how to do OOP “properly” to be complete rubbish:
Here are my views on changes to the PHP language and Backwards Compatibility:
The following are responses to criticisms of my methods:
Here are some miscellaneous articles:



