What is the 3-Tier Architecture?

By Tony Marston

14th October 2012

Introduction
What is a "tier"?
What is the difference between "N Tier" and "3 Tier"?
What the 3 Tier Architecture is not
What parts of an application can be split into layers?
What do you mean by "logic"?
The 1-Tier Architecture
The 2-Tier Architecture
The 3-Tier Architecture
The Rules of the 3 Tier Architecture
3 Tier Architecture in operation
Aren't the MVC and 3-Tier architectures the same thing?
What are the benefits of the 3-tier architecture?
The benefits of alternative Data Access layers
The benefits of alternative Presentation layers
Why do the Front End and Back End require different Presentation layers?
Front End Thin Clients and Back End Server
Example code - Front End to Back End (direct access)
Web Service Clients and Web Service Server
Example code - Front End to Back End (using web services)
Example code - business rules in the Business layer
Conclusion
References

Introduction

This article is in response to N-Tier Architecture - An Introduction written by Anthony Ferrara which I feel gives only a very limited view of what can be a complex subject. Different people have different ideas on how an application can be split into tiers, and different ideas on the benefits which can be gained from making such a split. I have been designing and building multi-tiered applications in different languages for over a decade, so my exposure to this subject has been quite extensive. I would like to share with you my experiences on this subject and hopefully give you a more detailed picture.

What is a "tier"?

A "tier" can also be referred to as a "layer". A wedding cake is said to have tiers while a chocolate cake is said to have layers, but they mean the same thing.

In the software world Tiers/Layers should have some or all of the following characteristics:

What is the difference between "N Tier" and "3 Tier"?

There is no difference. Some people refer to the N Tier Architecture where 'N' can be any number. I personally have found no use for any more than 3 tiers, which is why I always call it the 3 Tier Architecture. If you try to build an application with more than three layers then be aware that it may have a serious impact on performance, as discussed in Application Performance and Antipatterns.

What the 3 Tier Architecture is not

Some people consider that a web application is automatically 3 Tier as it has 3 separate components, as shown in figure 1:

Figure 1 - A Web Application

infrastructure-faq-06 (1K)

Although this would appear to satisfy the conditions outlined in What is a "tier"?, I feel that it fails on one important aspect. Just as a layer cake is made up of several layers of cake - you cannot combine a single piece of cake, a cake stand and a decoration and call it a "layer cake" - you require several layers of "cake". In order for your application to be called multi-layered it is the application on its own - which excludes all external components such as the browser and the database - which must be broken down into several layers. I am discounting everything outside of the application itself for the following reasons:

What parts of an application can be split into layers?

You cannot just take the source code for an application, chop it into parts and call each part a layer. You have to identify specific areas of responsibility, then identify the code which performs within each of those areas. As I said previously, I do not recognise any more than 3 areas, and those 3 are:

  1. Presentation logic - the user interface (UI) which displays data to the user and accepts input from the user. In a web application this is the part which receives the HTTP request and returns the HTML response.
  2. Business logic - handles data validation, business rules and task-specific behaviour.
  3. Data Access logic - communicates with the database by constructing SQL queries and executing them via the relevant API.

Although it may be possible to take any of the above areas of responsibility and break them down into even smaller components, such as with objects made from different design patterns, it may be unwise to treat each of those objects as a separate layer otherwise you may drown yourself in tiny details and lose sight of the big picture.

What do you mean by "logic"?

This may seem like a dumb question to some, but believe it or not there are some numpties out there who cannot identify what is covered by the term "logic" and what is not. They seem to think that everything to do with a computer application is "logic". They see some data in my data access layer which looks like HTML, and they immediately jump up and down like demented children and cry "You have presentation logic in your data access layer! You don't know what you're doing!" They see some data in my presentation layer which looks like SQL, and they immediately jump up and down like demented children and cry "You have data access logic in your presentation layer! You don't know what you're doing!" If you don't believe some of the peculiar opinions out there then take a look at the following:

Just in case you are one of these numpties, let me explain. Logic is program code, instructions which can be executed. Data is not logic, it is information which may be processed, manipulated or transformed in some way by that program code. Program code is fixed and exists in one place whereas data is variable and can pass through several layers of code. A piece of data may pass through several layers within an application, either from the user interface to the database, or from the database to the user interface, but it is never part of the logic of any of those layers. Data is processed by code, but is never part of the code.

Example 1: The Business layer may contain a piece of data which says "display field X as a dropdown list", but that is not presentation logic which is executed within the Business layer. Presentation logic is that piece of program code which actually constructs the HTML for the dropdown list. All the Business layer is doing is generating an instruction in the form of meta-data which is passed to the Presentation layer where that instruction is actually executed. It is only when that data is processed by the program code in the Presentation layer that the output is actually constructed, and it is the code which produces that output and returns it to the client which is presentation logic.

Example 2: The presentation layer may contain pieces of data which says "Fetch 10 records from the database starting a record number 30, and sort the result on field X", but that is not data access logic. It is only when that data is processed by the program code in the Data Access layer that the SQL query is actually constructed and executed, and it is the code which produces that query and sends it to the database which is data access logic.

There is a big difference between passing information to another component which can be construed as an instruction and actually executing that instruction. The instruction is merely a piece of data, a piece of information, and the "logic" only exists in that component which executes that instruction in order to produce a result. This difference has been recognised for years as:

The 1-Tier Architecture

Figure 2 is a simple diagram which shows a 1-Tier application where the Presentation logic, Business logic and Data Access logic are all contained within a single component:

Figure 2 - 1 Tier architecture

infrastructure-01 (5K)

Although this diagram apparently makes it easy to identify the different areas of responsibility, in real life the actual program code may be so inter-mingled, inter-twined and spaghetti-like that it would be extremely difficult to locate the boundaries between each area of responsibility. A blurry mess like this is shown in figure 3:

Figure 3 - Typical program with blurry boundaries

3-tier-architecture-004 (14K)

The 2-Tier Architecture

My first exposure to a software architecture which had more than one layer was with a compiled language where all database access was handled by a completely separate component which was provided by the vendor, as shown in figure 4:

Figure 4 - 2 Tier architecture

infrastructure-02 (8K)

This was a deliberate feature of the language as it enabled an application to be readily switched from one DBMS engine to another simply by loading a different data access component. No other part of the application was allowed to communicate with the database, so this component could be switched without affecting any other part of the application. This made it possible to develop an application using one DBMS, then deploy it with another.

Note that the presentation logic and the business logic are still intermingled.

The 3-Tier Architecture

This is where the code for each area of responsibility can be cleanly split away from the others, as shown in figure 5:

Figure 5 - 3 Tier Architecture

infrastructure-03 (8K)

Note here that the presentation layer has no direct communication with the data access layer - it can only talk to the business layer.

The Rules of the 3 Tier Architecture

It is simply not good enough to split the code for an application into 3 parts and call it "3 Tier" if the code within each tier does not behave in a certain way. There are rules to be followed, but these rules are pretty straightforward.

This cycle of requests and their associated responses can be shown in the form of a simple diagram, as shown in figure 6:

Figure 6 - Requests and Responses in the 3 Tier Architecture

3-tier-architecture-005 (2K)

If you look carefully at those layers you should see that each one requires different sets of skills:

Although it is possible for a single person to have all of the above skills, such people are quite rare. In large organisations with large software applications this splitting of an application into separate layers makes it possible for each layer to be developed and maintained by different teams with the relevant specialist skills.

3 Tier Architecture in operation

When an application is developed it is not (or should not be) constructed from a single large component. There are usually lots of small components (sometimes called 'modules', or 'classes' in OOP), each performing a particular function, and the application is the sum of those parts. This allows new functionality to be added without necessarily having any effect on any existing components. The advantage of a layered approach is that a component in a lower layer may be shared by multiple components in a higher layer, as shown in the figure 7:

Figure 7 - 3 Tier Architecture in operation

infrastructure-04 (8K)

Here you see that a component in the Presentation layer can communicate with one or more components in the Business layer. A component in the Business layer communicates with the component in the Data Access layer, but may also communicate with other Business layer components. There is usually only one component in the Data Access layer as the application database(s) are usually handled by a single DBMS engine. It is possible to switch to a different DBMS engine simply by changing this single component. It is also technically possible for different parts of the application to deal with different DBMS engines at the same time, as shown in figure 9.

In my largest application I have 2,000 components (user transactions) in the presentation layer, 250 in the business layer, and 1 in the data access layer. I have heard of some implementations which have a separate Data Access Object (DAO) for each individual table in the database, but more experienced developers can achieve the same functionality with just one. In my own implementation, for example, a single DAO can deal with every table in the database. However, I have a separate class file for each of the major DBMS engines - MySQL, PostgreSQL, Oracle and SQL Server - so I can easily switch from one to another by changing a single entry in my config file.

Note also that the connection to the database is not opened by any component within the Presentation layer. This should only be done within the Data Access layer when instructed to do so by the Business layer, and only the moment before an operation on the database is actually required. This is called the "Just In Time" (JIT) method as against the "Just In Case" (JIC) method. When the Business layer decides that it needs to talk to the database it follows these steps:

This approach allows an instance of my application to access database tables on more than one server, and even more than one DBMS engine.

Aren't the MVC and 3-Tier architectures the same thing?

There are some programmers who, upon hearing that an application has been split into 3 areas of responsibility, automatically assume that they have the same responsibilities as the Model-View-Controller (MVC) Design Pattern. This is not the case. While there are similarities there are also some important differences:

The overlaps and differences are shown in Figure 8 and Figure 8a:

Figure 8 - The MVC and 3-Tier architectures combined

infrastructure-faq-05 (5K)

Here is an alternative diagram which shows the same information in a different way:

Figure 8a - MVC plus 3 Tier Architecture

model-view-controller-03a (5K)

You may think that any implementation of MVC could automatically be regarded as an implementation of 3-Tier, but this is not the case. In every implementation of MVC which I have seen so far there has been one simple but fundamental mistake which makes this impossible, and that is where the database connection is made. In the 3-Tier Architecture all communication with the database, and this includes opening a connection, is done within the Data Access layer upon receipt of a request from the Business layer. The Presentation layer does not have any communication with the database, it can only communicate with it through the Business layer. With all the MVC frameworks I have seen so far the database connection is made within the controller, and the connection object is then passed down to the model which then uses it when necessary. This is a mistake often made by beginners and those who have been poorly educated.

The worst example of this mistake I have ever seen was where a Controller opened up 3 different connections to the same database server instance in order to communicate with 3 different databases in that server. Each of these connections was then passed to a different Model component which may not actually use that connection. An experienced programmer will immediately spot the flaws in this approach, flaws that could have a significant impact on performance:

Another mistake I have found with some implementations is that they think that data validation (sometimes called 'data filtering') should be performed within the controller before it is passed to the model. This does not fit in with the definition of the 3-Tier Architecture which states that such data validation logic, along with business logic and task-specific behaviour, should exist only within the business layer or model component. By taking data validation out of the model and putting it in the controller you are effectively creating tight coupling between the controller and the model as that controller cannot be reused with a different model, and tight coupling is something which is supposed to be avoided in order to produce 'better' software. Loose coupling would enable a controller to be shared by multiple model classes instead of being fixed to just one.

When properly implemented, an application which is developed using the 3-Tier Architecture should have all its logic - data validation, business rules and task-specific behaviour - confined to the Business layer. There should be no application logic in the Presentation and Data Access layers, thus allowing either of those two layers to be changed without affecting any application logic.

What are the benefits of the 3-tier architecture?

It is all very well describing something like the 3 Tier Architecture, but nobody is going to make the effort to switch from their current arrangement unless there are benefits to be made, so what exactly are the benefits of this architecture? According to some there are lots of expenses but no benefits at all, as expressed in the following Sitepoint blog:

It's main function (independence of user interface, business rules and data storage/retrieval) only helps when migrating or extending to another script-language/data engine/platform. But this only happens very very few times in an Application Lifetime.

This is a very narrow-minded view from a person of limited experience. The aim of using the 3-Tier Architecture is not just to make it easier only when you change your database engine or programming language. It is also useful when you want to either replace your Presentation layer or create an additional Presentation layer. If you have ever worked on a variety of 3-Tier and non-3-Tier applications you would be able to see the differences, and therefore the advantages, for yourself.

The main advantages of the 3 Tier Architecture are often quoted as:

Another not-so-obvious benefit which can only come from actual exposure to having developed multiple applications using the 3-Tier Architecture is that it becomes possible to create a framework for building new applications around this architecture. As each of the layers specialises in just one area of the application it is possible to have more reusable components which deal with each of those areas. Such components can either be pre-built and delivered as part of the framework, or generated by the framework itself. This reduces the amount of effort needed to create a new application, and also reduces the amount of effort needed to maintain that application.

If you think that such a framework has not been written yet then you have not heard about Radicore.

The benefits of alternative Data Access layers

A lot of critics of the 3-Tier Architecture seem to think that the ability to switch from one DBMS to another is not worth the effort as it rarely happens in real life. While it is true that, once developed, an application will rarely be switched to a different DBMS, a lot of organisations are now wishing that they had that ability when they compare the costs of their proprietary databases with the modern and far cheaper open source equivalents.

Switching to a different DBMS after an application has been built is not the only benefit when you consider that not everyone works on a single legacy application for a single organisation. There are software houses who develop and maintain a variety of applications for a variety of customers, so speed of development, cost of development, and providing their customers with more choices is what differentiates them from the competition and is likely to be a selling point instead of a rarely-used option. Consider the following:

By giving your customers the ability to easily switch from one DBMS to another without enormous expense and effort you will be pleasing your customers and displeasing your competitors.

The ability to switch from one DBMS to another does not, or should not, restrict you to just one DBMS at a time. If each component in the Business layer is responsible for creating and communicating with a component in the Data Access layer it should be possible to allow more than one component to exist at the same time, as shown in figure 9:

Figure 9 - Using multiple objects in the Data Access layer

3-tier-architecture-009 (2K)

Here you can see that instead of just "alternative" components in the Data Access layer you actually have the option of "additional" components. This will allow, for example, part of your application to access a MySQL database while another part accesses a PostgreSQL/Oracle/SQL Server database.

The benefits of alternative Presentation layers

A lot of critics of the 3-Tier Architecture seem to think that the ability to switch from one Presentation layer to another is something else which has very little value in the real world, but yet again they are being narrow-minded and blinkered in their viewpoint. I first encountered the 3-Tier Architecture when using a compiled language which produced applications for the desktop. As soon as the internet revolution got into full swing and more and more organisations wanted a web site, the authors of this language added in the ability to generate a new presentation layer based around the HTTP protocol and HTML forms. This new Presentation layer still accessed the existing Business and Data Access layers, so it did not involve a full application rewrite, just the development of a new set of components for the Presentation layer. This new layer was not instead of the old layer, it was in addition to the old layer, which made it possible for the original desktop application to be used by the in-house staff while internet visitors used the new HTML layer. Developers who used this language liked the idea that they could build a web interface into their existing application and make use of existing components instead of having to rewrite the whole application from scratch.

The ability to switch from one Presentation layer to another does not, or should not, restrict you to just one Presentation layer at a time. Each Presentation layer has its own set of components and is activated in a different way by a different set of users, but they all then communicate with the same set of components in the Business and Data Access layers. It should then be possible to allow more than one Presentation layer to be used at the same time. Thus instead of just an "alternative" Presentation layer you actually have the option of "additional" Presentation layers. This will allow one set of users to access the application through one Presentation layer while other sets of users access it through different Presentation layers which have been tailored just for them.

This choice between two Presentation layers, one for in-house staff and another for internet visitors, has been extended in recent years to cover additional sets of users. I have personally worked on several e-commerce applications which, as well as a Business-to-Consumer (B2C) site they also have a Business-to-Business (B2B) site - sometimes known as a Supplier Portal - and increasingly an additional site for dealing with web services. I have also helped an organisation go multi-national with copies of their UK website ported to different servers in different languages, all being served from the same back-end application and database. This then produces an application which has several Presentation layers or "windows", as shown in figure 10:

Figure 10 - A typical application with multiple "windows"

3-tier-architecture-006 (2K)

Just suppose each of these "windows" was treated as a separate application instead of a small part of a much larger application? None of these applications would share any component in any of the other applications, which would result in a duplication of effort. Even though each of these "windows" would have its own presentation logic, it would also have its own business logic and data access logic. This would result in the situation shown in figure 11:

Figure 11 - Each "window" has its own layers

3-tier-architecture-007 (4K)

If you wanted each of these "windows" to enforce the same business rules you would have to maintain the program code in each of the different business layers, which would be a costly duplication of effort as well as a potential problem area should the code in one "window" not be kept in sync with the others.

Just suppose the first (or primary) application had been developed using the 3-Tier Architecture with its reusable Business layer and Data Access layer components? All the additional (or secondary) "windows" would be much smaller as they would not require their own set of business and data access logic, they would be able to share the logic which was written for the first application. This arrangement is shown in figure 12:

Figure 12 - Multiple Presentation layers sharing a single Business layer and Data Access layer

3-tier-architecture-008 (4K)

Here you can see that only one application - the back end management application - has all three layers of code while all the other applications are nothing more than simple "windows" which consist of a separate presentation layer which connects to the shared business layer (and through that the shared data access layer).

As the code to enforce the business rules is maintained in a single place then you also eliminate the problem of synchronising those rules in multiple places. You can make a change to a single component in the Business layer and have that change immediately picked up (or "inherited" using the parlance of Objected Oriented programmers) by all the various "windows".

As each of these additional "windows" is able to reuse a significant amount of existing code, the observant among you will immediately notice that this should also make them quicker, easier and cheaper to develop. How much cheaper depends on how you build your front ends. For example, if you are a follower of the Model-View-Controller design pattern you should see that the existing Business layer already provides the Model, so you have nothing to design and develop for each front end except the Controller and the View. The skills required here are little more than HTML, CSS and JavaScript, while the heavy lifting - the database design, the processing of business rules and the generation of complex SQL queries - can be left to the big boys in the back office.

Why do the Front End and Back End require different Presentation layers?

This is a question I am often asked by inexperienced people, and the reasons, which are detailed in Web Site vs Web Application, can be summarised as:

The screens in the front end need to attract visitors, just like a showroom or a high street store. They are free-form and often built using complex HTML, CSS, JavaScript and lots of sexy graphics. They may also contain code to deal with Search Engine Optimisation (SEO), analytics, affiliate marketing, advertising banners and other marketing stuff.

The screens in the back end are a lot simpler as all they need do is allow members of staff to do their jobs as quickly and efficiently as possible, and therefore need to be functional rather than sexy. They don't need complex HTML, CSS or JavaScript, and certainly don't need sexy graphics, SEO or other marketing stuff. As they deal with database data which is organised into rows and columns they can be boiled down into two common screen structures - the LIST view which shows multiple rows in a horizontal arrangement and the DETAIL view which shows a single row in a vertical arrangement. This means that the screens in the back end can be built more easily from standard templates whereas the screens in the front end are usually hand crafted one by one. There are usually some additional screens in the back end which might need complex SQL queries so that the data can be extracted and presented in a variety of management reports.

There are also more screens in the back end than in the front end (the ratio can be as much as 100:1), and not every function that is available in the back end will be available in the front end while anything which can be done in the front end should also be possible in the back end. For example, in e-commerce applications the front-end website is used by customers to enter their orders, but there should always be an order entry function available in the back office.

Because of these significant differences between the front end and the back end is should be easy to see that:

In my opinion it would be extremely unwise to see the back end application as an extension to the front end website, or the front end as an extension to the back end. The back end administrative application gives its users, who are members of staff (and possibly management), complete access to every aspect of the company's business. The front end website, on the other hand, gives its users, who are casual visitors, extremely limited access.

Front End Thin Clients and Back End Server

You should have noticed in the preceding paragraphs that I have referred to the first or "primary application" and a series of one or more "secondary windows". When developing a website for a new business the most important question to be asked is "What is the primary application and what are the secondary windows?" This is where a large number of developers make a simple but costly mistake by choosing the front-end website as the primary application and totally ignoring the need for a back-end administrative application.

Those of you who have been involved in the development of e-Commerce applications for various organisations should immediately recognise the folly in this decision. Just as an organisation would not be foolish enough to open up a bricks-and-mortar store in the high street without having all the necessary infrastructure in place, an organisation should not attempt to open up an internet store without having all the necessary software infrastructure in place. If you don't know what I mean by infrastructure then you should go to the back of the class and hang your head in shame. By "software infrastructure" I mean the following:

The needs of the front-end website, the electronic store, are quite simple:

  1. Display products.
  2. Accept sales.

The needs of the back-end application - sometimes referred to as Order Processing, Order Fulfilment, Logistics, Supply Chain Management or Enterprise Resource Planning (ERP) - cover every aspect of the organisation's business:

  1. Maintain product data - products, product categories (which may have hierarchies), product features (availability, applicability and compatibility), product prices (standard prices, contract prices), surcharges (such as as sales tax and shipping), discounts (either fixed value or a percentage).
  2. Maintain party details - customers and suppliers, classifications, roles, contact mechanisms (postal addresses, email addresses, telephone numbers).
  3. Contract prices and/or discounts, either for specific parties or for party categories.
  4. Customer Relationship Management (CRM) - emails received, emails sent, notes on conversations.
  5. Content Management System (CMS) - maintaining text for static pages.
  6. Maintain order details - sales orders, order adjustments, item adjustments, purchase orders, non-conformance reports, transfer orders (for inventory).
  7. Invoicing - invoices, credit notes, PDF generation, financial reports.
  8. Shipments - customer shipments, customer returns, supplier shipments, supplier returns, transfers (in and out), packages, package contents, returned material authorisations (RMAs from customers) and non-conformance reports (NCRs for suppliers).
  9. Inventory - facilities, containers, items, receipts, pick lists, issuances, stock checks, variances, lot numbers, reorder guidelines.
  10. Management reports.

Just as a high street store cannot exist without the infrastructure to support it, neither can an electronic store (the website) exist without its administrative application. Just as in the world of bricks and mortar the infrastructure is built up first and the stores in the high street are opened up last, so should it be in the world of electronic stores. Just as in the physical world the high street stores use the procedures and processes laid down by the management team in head office, in the electronic world the front-end websites should use the procedures and processes built into the back-end management application. Just as in the physical world each high street store is merely a small representation of the business as a whole, in the electronic world each front-end website is nothing more than a small window into the much larger back-end management application - it needs nothing more than a small presentation layer which connects into the back-end business layer. Just as in the real world any high street store can receive a make-over without having any effect on the infrastructure or the head office, in the electronic world a website's presentation layer can receive a make-over without having to rewrite any of the business logic in the back-end administrative application.

So, just as in the world of bricks and mortar the supporting infrastructure is built first and any customer-accessible stores are built last, in the electronic world the back-end administrative application should be built first and any customer-facing websites built last.

The centre of the software application is always the data which is stored within the database, with members of staff and visitors each having their different "windows" into that data. The business rules are constructed by the administrators and held within the larger back-end administrative application, yet shared with any number of smaller front-end websites. This arrangement is shown in figure 13:

Figure 13 - A small Front End sharing the components in a larger Back End application

front-end-back-end-02 (5K)

The primary purpose of a front end website is presenting the organisation to the outside world in order to attract customers. The primary purpose of the back end application is the administration of the organisation's data and the enforcement of business rules. They both share the same pool of data, they both share the same set of business rules, and it is only in the way that the data is presented to their respected sets of users, and the functions which they are able to perform, which is different. You should see that the terms "presentation", "business rules" and "data" are a perfect match for the different layers in the 3 Tier Architecture, so by using this architecture to build your software you will be able to have any number of unique presentation layers which all share a single business and data access layer.

When I say that the back-end application is larger than the front-end websites I don't mean slightly larger, I mean orders of magnitude larger. For example, I have built a back-end e-commerce application as a package which is used by several different companies selling different goods through their own bespoke front-end websites. They each use a copy of the same back-end software with their own copy of the database. The average number of screens in these front-ends is about 20, so when you compare this with my back-end application which has 2,000 screens you will see that each front-end is only 1% the size of the back-end. To put in another way, my back-end application is 100 times larger than any front-end. Because the front-ends are so small (they require nothing more than a simple presentation layer which can communicate with the existing business and data access layers) it is a relatively quick, and therefore inexpensive, process to build a new bespoke front-end for a new client, yet they have immediate access to a large and powerful back-end application.

Because the front-end website calls upon the services provided by the back-end application the two can be said to exist in a client-server relationship with the front-end being the "client" and the back-end being the "server".

Example code - Front End to Back End (direct access)

Describing how easy it is for the front end to connect to the back end is not very convincing without some example code. Below are some examples of functions which the front end can use to retrieve product data. These use the singleton::getInstance method to create an instance of the 'product' class (which exists in the Business layer of the back end application), load in optional data where necessary, then activate the getData method to retrieve data from the database. Some of the more complicated options which are available have been left out for the sake of simplicity.

Note that in keeping with the rules of the 3-Tier Architecture the Presentation layer does not connect to the database and pass this connection to the Business layer object. It is up to the Business layer object to make the connection when it is necessary.

The get_product_array function will retrieve those records which match the $where criteria and will be sorted by the $orderby value. Pagination is controlled by the values for $pageno and $rows_per_page.

function get_product_array ($where=null, $orderby=null, $pageno=1, $rows_per_page=12)
// get array of multiple products
{
    if (empty($where)) return false;

    $dbobject =& RDCsingleton::getInstance('product');
    $dbobject->setOrderBy($orderby);
    $dbobject->setPageNo($pageno);
    $dbobject->setRowsPerPage($rows_per_page);
    $rowdata = $dbobject->getData($where);

    $numrows = $dbobject->numrows;
    $lastpage = $dbobject->lastpage;

    return array($rowdata, $numrows, $lastpage);

} // get_product_array

The get_product_data function will retrieve the details for a single product which is identified by its primary key.

function get_product_data ($product_id=null)
// get details for a single product
{
    if (empty(product_id)) return false;
		
    $where = "product_id='$product_id'";

    $dbobject =& RDCsingleton::getInstance('product');
    $data = $dbobject->getData($where);
    if (!empty($data)) {
        $data = $data[0]; // return 1st row only
    } // if

    return $data;

} // get_product_data

Web Service Clients and Web Service Server

Experienced software developers may spot a small limitation within the above arrangement - in order for each Presentation layer to communicate directly with the Business layer both layers must be written in the same language and reside on the same server. It is possible for different Presentation layers to reside on different servers, but only if they have their own copies of the code for the Business layer and Data Access layers. The same experienced software developers should also know of a different approach - web services. This means that instead of having to communicate directly with the back-end application the front-end simply sends a request over the internet which is received, processed, and the response returned over the internet. Thus the front-end website acts as a web service client while the back-end application acts as a web service server, as shown in figure 14:

Figure 14 - Linking the front and back ends with Web Services

front-end-back-end-03 (12K)

While it is possible for the web service client and server to exist on the same physical machine and be written in the same language (I do all my development and testing on a single PC, for example), it is not uncommon for the client and server to be written in different languages and be located on servers which are miles apart. This opens up a world of opportunities.

Example code - Front End to Back End (using web services)

In the following examples I have modified the previous functions so that I can switch from direct access to web service access simply by setting an option in the CONFIG file. These use the get_TRANSIX_client function to obtain an instance of the web service client which sends the request over the internet to the web service server which has been built into the back end application. This then uses a copy of the function which has direct access to the database. Even though the response is returned in XML format it is automatically converted into a PHP array so the front end Presentation layer does not have to know how the data was obtained. It simply calls a function to get some data, and how that data is obtained is irrelevant.

Note that it is physically impossible to send a database connection over the internet, so the fact that the Presentation layer never creates one in the first place means that I don't have a connection which is wasted.

This function retrieves multiple records with pagination options. Note that the web service client uses the getMany() method for this purpose.

function get_product_array ($where=null, $orderby=null, $pageno=1, $rows_per_page=12)
// get array of multiple products
{
    if (empty($where)) return false;

    if (defined('USE_WEB_SERVICES')) {
        require_once('transix_client_api.inc');
        $dbobject = get_TRANSIX_client('Product');
        $args['where']     = $where;
        $args['orderby']   = $orderby;
        $args['page_size'] = $rows_per_page;
        $args['page_no']   = $pageno;
        $rowdata = $dbobject->getMany($args);
    } else {
        $dbobject =& RDCsingleton::getInstance('product');
        $dbobject->setOrderBy($orderby);
        $dbobject->setPageNo($pageno);
        $dbobject->setRowsPerPage($rows_per_page);
        $rowdata = $dbobject->getData($where);
    } // if

    $numrows = $dbobject->numrows;
    $lastpage = $dbobject->lastpage;

    return array($rowdata, $numrows, $lastpage);

} // get_product_array

This function retrieves a single record which is identified by its primary key. Note that the web service client uses the get() method for this purpose as it is only expected to provide a single row from the database.

function get_product_data ($product_id=null)
// get details for a single product
{
    if (empty($product_id)) return false;

    $where = "product_id='$product_id'";

    if (defined('USE_WEB_SERVICES')) {
        require_once('transix_client_api.inc');
        $dbobject = get_TRANSIX_client('Product');
        $args['where'] = $where;
        $data = $dbobject->get($args);
    } else {
        $dbobject =& RDCsingleton::getInstance('product');
        $data = $dbobject->getData($where);
        if (!empty($data)) {
            $data = $data[0]; // return 1st row only
        } // if
    } // if

    return $data;

} // get_product_data

Example code - business rules in the Business layer

One common question I am asked by novice programmers is "How can you put the code for your business rules in the Business layer component?" A lot depends on how the component is actually built, but the RADICORE framework makes this easy by providing components which have empty compartments into which you can insert your code. Each of these compartments will be executed at a predetermined point in the processing sequence, such as pre-insert, post-insert, pre-update, post-update, so when you put code into one of these compartments you know exactly when it will get processed.

For example, suppose there is a business rule which states "when an order's status is changed this must be recorded in the status history table". This can be achieved with the following code in the _cm_post_updateRecord() method of the ORDER_HEADER class:

function _cm_post_updateRecord ($rowdata, $old_data)
// perform custom processing after database record is updated.
{
    if ($rowdata['order_status_type_id'] != $old_data['order_status_type_id']) {
        $dbobject =& RDCsingleton::getInstance('order_status_hist');
        $data['order_id']             = $rowdata['order_id'];
        $data['order_status_type_id'] = $rowdata['order_status_type_id'];
        $data = $dbobject->insertRecord($data);
        if ($dbobject->errors) {
            $this->errors = array_merge($this->errors, $dbobject->errors);
            return $rowdata;
        } // if
    } // if

    return $rowdata;

} // _cm_post_updateRecord

Note that the function which calls the updateRecord() method on the ORDER_HEADER object is totally oblivious to this business rule, so does not require extra code to carry it out. This mechanism can be extended so that the ORDER_STATUS_HIST component, when inserting a record with a particular status value, can automatically send out an email to the customer regarding that change in status. Again this logic is hidden from the ORDER_HEADER object, or any other object which calls the insertRecord() method on the ORDER_STATUS_HIST component.

By putting the code which carries out a business rule into the right place in the right object it is possible to guarantee that the rule will be carried out by all users of that object. By putting the code into the Business layer which is shared by multiple Presentation layers you can guarantee that each of those Presentation layers will share the same business logic without even being aware that any logic exists. So when a Presentation component issues the instruction "update order status" it is unaware that a record is written to the history table or that an email is sent out. In this way each front end Presentation layer can be kept as lean and lightweight as possible as all the heavy lifting is carried out by Business layer components in the back end.

Conclusion

I hope that I have managed to convince you that the 3-Tier Architecture is not just an academic exercise with huge costs and limited benefits. Once you have made the first step then other possibilities come within easy reach:

When implemented correctly the 3-Tier Architecture can provide a whole series of benefits which would otherwise be very expensive to implement. I would ask you to try it and see, but your current architecture is probably so outdated and badly written that it you can do no more than dream about it. What bad luck!

References

If you want to read some criticisms of my approach then please take a look at the following:


© Tony Marston
14th October 2012

http://www.tonymarston.net
http://www.radicore.org

counter