Physical Layers
by kirk knoernschild
Statement
Module relationships must not violate logical layer relationships.
Description
It’s common knowledge that when designing systems of any degree of complexity, the presentation, business logic, and data access should be separated into distinct layers. There are two important considerations when separating the layers.
Each layer should be responsible for a functional aspect of the application. The most common layering scheme I’ve seen used is a three layer approach consisting of presentation, business logic and data access. The presentation layer is responsible for structuring and rendering the user interface. A business logic, or domain, layer is responsible for containing the business objects, and a data access layer is responsible for encapsulating access to the persistent data store and external systems. Typically, you’ll apply certain patterns to each layer, such as MVC in the presentation layer, and DAO in the data access layer, contributing to a well-defined set of functionality within each layer. Such logical separation of functionality can help ease maintenance of the application.
Functionally separating your application into logical layers is not enough, though. One of the oft-cited advantages of separating the application into various layers is to allow you to reuse the functionality exposed by lower layers. For instance, if you’re developing a web application, you may find a need to reuse the business logic within another web application, or possibly even a batch style application. To achieve this, you cannot only logically divide your layers based on behavior, but also physically separate the layers structurally. Figure 7.3.1 shows the allowable structural relationships between the physical layers. Note that it’s important that AcyclicRelationships exist between the components. To summarize, logical separation helps you ease maintenance, whereas physical separation helps you increase reusability.

Figure 1 – Allowable Relationship between physical layers
Implementation Variations
To effectively divide your application into PhysicalLayers, your components must exhibit Acyclic Relationships. Since you cannot reuse any component without all dependent components, cycles in the relationships between the components in the physical layers prevents you from achieving the structural separation you want. This holds true regardless of how well you’ve logically separated the behavioral aspects of your application.
An important consideration when defining your physical structure is whether you’ll use a strict or relaxed layering scheme.
With all of this said, I wouldn’t necessarily begin by trying to exactly define your physical structure based upon what you think you might want to reuse. This predictive form of reuse typically doesn’t work very well, and you’ll wind up with a bunch of components where not one can be used independent of others. Instead, I’d suggest starting out with fewer components, carefully managing the relationships between classes, and break apart the components as you find you need reuse. Using tools such as Jdepend can help you understand and enforce your logical relationships, lending you the ability to refactor to more flexible physical relationships when you find the need.
Consequences
Separating your physical layers helps ease some kinds of maintenance. For instance, changes to the presentation layout are isolated to a single level. Behavioral changes to your business logic are also isolated. However, there are some types of changes that are very difficult to isolate. Adding new columns to a database table that must be displayed on the user interface is typically going to require changes across all of the levels. But the value in separating your PhysicalLayers is still useful because managing these changes is much easier. A Test Module can be used to independently test the changes made in a specific level, allowing you to ensure that your modification functions as expected before changing the other levels.
If you are lucky enough to have isolated change to a single level, instead of deploying the entire application, you have the option of deploying only the physical component that has changed. This type of deploy can be especially useful if there are multiple applications that use the component that has changed. Instead of deploying each application in it’s entirety, you can deploy only the component that has changed.
It’s much easier to enforce physical separation than it is logical separation. You may have a wonderful initial class structure that appears to be functionally separated. But how do you enforce and maintain this logical separation as the system grows? If even a single violation of your logical layers creeps into your structure, the entire logical layer structure is compromised. While tools such as Jdepend can help enforce logical separation, it’s still cumbersome of enforce. On the other hand, the separation between physical layers can be strictly enforced by performing a Levelized Build.
Sample Code
It’s common when developing business applications to separate your application into three layers. The presentation layer is responsible for structuring and rendering the user interface. A business logic, or domain, layer is responsible for containing the business objects, and a data access layer is responsible for encapsulating access to the persistent data store and external systems.
The business objects in the business logic layer are typically constructed using a combination of key values and data provided by the user interface in conjunction with data retrieved from a persistent datastore. In web applications, presentation frameworks, such as Struts, help shield the developer from working with variou http request objects, and instead pass the data from a page using an ActionForm, which is a POJO. It would seem, therefore, that there could be little harm in using the ActionForm to help build the business object.
Consider an enterprise billing application that allows users to pay bills through a web interface. There are two mechanisms through which a bill can enter the system. Smaller customer typically send their bills through standard mail, and the user keys the data off of the bill into a web interface and saves the information to a database. Large customers send their bills electronically using a standard EDI format. The EDI feed is processed by a batch application that runs nightly and saves the bills to the database. Regardless of the input mechanism, all bills must pass through the same set of validation rules before being saved. Certainly we want to avoid replicating the domain logic and persistence mechanism across the web and batch applications.
From the web world, the Bill instance is typically created using a bill id that is passed from a JSP page via an ActionForm. Initially, it may seem feasible to simply pass the ActionForm to the Bill instance, and allow the Bill to use the key value to initialize itself. Knowing that I’m likely going to need flexibility in how I load the data for Bill instances, I create a BillEntityLoader interface that is passed to the Bill class when a Bill instance is requested. This Bill class is shown in Figure 1.
package com.extensiblejava.bill;
import com.extensiblejava.audit.*;
import com.extensiblejava.financial.*;
import java.math.*;
import com.extensiblejava.bill.data.*;
public class Bill {
private BillDataBean billData;
public static Bill loadBill(BillEntityLoader loader) {
return loader.loadBill();
}
public Bill(BillDataBean billData) {
this.billData = billData;
}
public String getBillId() { return this.billData.getBillId().toString(); }
public String getName() { return this.billData.getName(); }
public BigDecimal getAmount() { return this.billData.getAmount(); }
public BigDecimal getPaidAmount() { return this.billData.getPaidAmount(); }
public void pay() {
if (this.billData.getPaidAmount() == null) {
Payment payer = new Payment();
this.billData.setPaidAmount(payer.generateDraft(this));
this.persist();
}
}
private void persist() {
BillDb.update(billData);
}
}
Listing 1: The Bill Class
The BillEntityLoader accepts the BillDetailForm, which extends the Struts ActionForm, so that it can use the billId to retrieve the appropriate information for the Bill being created. While not shown, we’ll assume the appropriate Struts action class is instantiating the DefaultBillEntityLoader and passing it to the loadBill method. The DefaultBillEntityLoader loads the BillDataBean from the database, as shown in Listing 2.
package com.extensiblejava.bill;
import com.extensiblejava.bill.data.*;
import com.extensiblejava.ui.BillDetailForm;
public class DefaultBillEntityLoader implements BillEntityLoader {
private BillDetailForm billForm;
public DefaultBillEntityLoader(BillDetailForm billForm) {
this.billForm = billForm;
}
public Bill loadBill() {
BillDataBean billBean = BillDb.getBill(new Integer(this.billForm.getBillId()));
return new Bill(billBean);
}
}
Listing 2: The DefaultBillEntityLoader
At first glance, this structure seems sensible. The Bill class depends upon an abstract BillEntityLoader, and is therefore effectively decoupled from any concrete implementations. Therefore, the Bill class can use different implementations of BillEntityLoader and the design seems quite flexible. However, as can be seen in Figure 1, the DefaultBillEntityLoader being passed to the Bill is dependent on the BillDetailForm, which extends the Struts ActionForm class. This relationship results in a cyclic dependency with the ui.jar module, and effectively couples the bill.jar module to both the ui.jar and struts.jar modules. While we have a flexible class design that is nicely layered, our module structure is not layered and ultimately prohibits us from reusing the bill.jar module without these other modules.

Figure 1: Bill module Violating Layered Structure
In this situation, the remedy is rather simple. Because our Bill is coupled to the BillEntityLoader interface, and not the concrete implementation of the DefaultBillEntityLoader, we can SeparateAbstractions, and refactor by escalating the DefaultBillEntityLoader to the com.extensiblejava.ui package. Upon doing so, the bill.jar is now completely independent of Struts, as illustrated in Figure 2.

Figure 2: The Correct Layered Structure
It’s certainly worth mentioning, that in this example, we could have gotten away with leaving the DefaultBillEntityLoader in the bill.jar component. Since the BillDetailForm only extends the ActionForm, which is a POJO, it won’t attempt to use any Struts specific functionality that is tied to a J2EE container. Therefore, our batch application would have likely worked fine since the default ClassLoader for our batch application would likely have never come across a situation where it tried to load a class specific to the container, such as HttpServletRequest. However, it’s confusing to require deploying the struts.jar component with our batch application, has a very bad smell, and increases the risk of strange errors at runtime.
Wrapping Up
Layering your application is a common architectural pattern. When layering an application, it’s important to separate behavior as discreet and granular modules, but it’s also important to separate the layers structurally. A flexible class design that adheres to a layered structure can be compromised if our module structure isn’t layered, as well. Unfortunately, it can be incredibly difficult to identify violations in the layered module structure. One way to help enforce the structure is through a LevelizedBuild. Tools can also help.
Comments
[...] and layers, what’s the difference? Layers have much more do with responsibility, whereas levels have [...]