Thursday, January 3, 2008

Tiers and Layers: Same thing?

Alert: some of you will find this conversation esoteric and irrelevant, figuring that the subtle difference between tiers and layers is too minor to make a difference. Others, like me, will find the difference to be significant, especially if you're trying to build highly robust, scalable, maintainable, resilient applications.

In general, a multi-tiered application is one that can be, but isn't necessarily, distributed on physically separate computing systems such as a workstation, application server, database, and/or mainframe.

A correctly multi-layered application has a clear and distinct grouping and/or separation between logical functions such as presentation, business logic, and persistence.

Interestingly, we often think of the layers and tiers as being in alignment, i.e. the presentation layer runs on the workstation, the business logic runs on the application server, and the persistence layer is the database server. Well, kinda, sorta, but not really. An example will help, but first, let's drill into the specifics a little deeper.

Physical Tiers
Application tiers are the physical computers on which the various components run. This would include a workstation/laptop/PDA/cell phone, a server/midrange system or cluster, a database server, and or a mainframe. Applications designed to operate in a multi-tiered environment are said to be horizontally scalable, that is, performance and experience can be enhanced by distributing the components across the tiers.

By contrast, consider 1990's style two-tiered applications, sometimes referred to as having a Client/Server Architecture. These applications were constructed such that the presentation, application, and business logic were required to the run on the desktop, and there was no physical way to separate them. Today's typical web applications provide a loosely coupled integration of the desktop and midrange/server tiers through the use of industry standard protocols; TCP/IP, HTTP(s), and HTML.

So, here's an interesting situation. Let's say that you have a server running Apache and WebSphere (not what we do, but certainly within the range of normal), and on that same server you decide to load a browser and launch a web-based application. The browser, the web server, and the app server are all running on the same computer. Does this mean you have a one-tiered application? No. The number of tiers an application has relates to how many systems across which the application could be deployed with no coding changes (config files don't count).

In our example, so long as we're using industry standard protocols, the application would be at least two tiered (the web server *could* just be a pass-through).

Logical Layers
Like tiers, an application's layers should be loosely coupled; only now it is to maximize flexibility, reuse, and maintenance. Unlike, tiers however, layers have nothing to do with the number of physical devices employed. A Layer is a group of course grained like-functions such as presentation, business rules, persistence. Sublayers can be used to create manageable stratification of functions as well. The key point here is that failure to properly layer an application will lead to misplaced responsibility, code maintenance problems, and often performance issues (ironic since this is usually the reason cited for not properly layering).

A book titled Learn Java ServerPages in 21 Days, provided an example of an SQL Query embedded in a Java scriplet on a JSP. Hmm, seems to be a violation of the clean separation concept. One of the reasons we usually recommend against calling JSPs directly from a browser is it's easy for developers to improperly cross layer boundaries (such as putting SQL in a JSP) unless they're very disciplined. In our date-driven environment, discipline often gives way to delivery.

The first thing to remember about layers is that they should be kept isolated from each other; i.e. each should have a defined API such that the encapsulated code could change leaving the loosely-coupled consumers intact. A logging utility is a good an example. A developer should be able to replace her entire application's logging system without altering a single line of database, business rules, or presentation code. Furthermore, the logging layer should have no knowledge of the business problem being addressed. There should not be a single control structure, if-then-else clause, or code sequence in the logging layer that references any business objects, beyond some abstract interface (i.e .toString()).

While most everyone will agree to this clean separation in a logging layer, some will push back when it comes to the presentation layer. After all what's wrong with the presentation layer having explicit knowledge of the database tables from which it derives content? Or, what's wrong with a persistence layer that returns different HTML strings depending on some rule governing the data? In summary a change to an internal function (non-public API and/or code) in one layer should never cause a change in another layer.

If a business rule, encapsulated in a properly configured business logic layer, some how manipulated presentation code (say returning a specific HTML sequence), then the entire application is now bound to a specific user interface; possibly a specific version of a specific browser. Talk about tight coupling! This kind of misplaced responsibility impacts design, maintenance, and time-to-market for subsequent product upgrades. Furthermore, it is never necessary - and that's important. Why incorrectly design and code an application, when a correctly layered approach will yield the same business functionality, without the violation of a well-known, proven standard?

This is not the same as saying a new business requirement can't cause changes in multiple layers - that happens all the time, but no layer should have explicit knowledge of the internal working of another layer. No layer should be functionally dependant on the internal operation of another layer.

Layers and Tiers
Earlier we mentioned that tiers and layers are sometimes thought to be aligned, almost to the point of being the same thing. In a classic n-tiered, web-based application, the presentation layer clearly spans two tiers. In J2EE, the HTML pages with their associated images, Javascript, and CSS files are easily identified as presentation layer artifacts as these are rendered on the user's workstation. Additionally, the Java servlets and Java ServerPages, are also considered part of the presentation layer even though these never leave the application server.

A common mistake (and point of confusion) occurs when developers insert business logic in-line with their servlet code. While this is understandable when a developer has a very small application (one servlet, one page), and for projects in the very early stages of prototyping, it is not a condition that should wind up in production. One way to keep yourself honest is to put all of an application's servlet code in one Java package, and the business and domain objects in a separate package (or even a separate project!).

From time-to-time, you may find that an ugly class is needed to compensate for a design which is good, but not perfect. It is common practice to create a package of utility/helper classes that contain cross-layer knowledge and to place these within the presentation layer. Remember as we move from the presentation layer back through our design to the business layer and ultimately back to the persistence layer our potential for reuse should increase. Data is the most reusable asset in our environment, and presentation code is the least.

Care to comment on this content? Click the feedback link to write to us.

Follow by Email