Layering was the topic of Chapter 3. I described the design of the internet as a series of stacked layers.
As a developer of internet applications, you can also use layering as an architectural strategy in your code.
In this chapter, I will explore how to introduce layering into new projects.
Three layers
There is no ‘correct’ architecture for internet applications. Different situations will require different architectures. Some architectures are surprisingly versatile: they appear in response to widely varied design problems. By studying these architectures, we benefit from the wisdom and hard-learned lessons of experts.
One of the most versatile and well-known architectures is the three-layer architecture. It is used extensively in internet development as well as enterprise software development.
The three-layer architecture divides a system into three layers: [1]
1 |
Presentation |
2 |
Domain |
3 |
Persistence |
Presentation logic
The presentation logic is responsible for formatting and displaying data for user interaction. The name presentation logic refers to its responsibility for presenting information to the user.
In a web application, the presentation logic might include:
-
Code that generates HTML
-
Code that decodes submitted HTML form data
-
Styles defined in CSS
-
JavaScript code to show alerts or animations
Presentation logic can encompass multiple user-interfaces. The presentation logic might also include:
-
A native client to install on Windows, Mac or Linux
-
Mobile applications for installation on iPhone or Android
-
Command-line clients for use by developers or in scripts
-
Public APIs that allow other developers to integrate with your system
Domain logic
The presentation layer depends on the domain logic to perform the core functionality of an application.
The domain logic is responsible for handling core “business” services. The word domain in domain logic means ‘an area of activity’ (i.e., the problem domain or the business domain).
In a typical web application, the domain logic might perform the following services:
-
Managing the contents of a shopping cart
-
Calculating totals and sales tax payable
-
Processing a payment
-
Determining which warehouse should handle an order
-
Calculating the number of “likes” on a post
-
Ensuring that private profiles stay private and that anonymous users can only retrieve public profiles
-
Detecting spelling errors in a submission
Note that layering means that the domain logic should be unchanged when the presentation logic changes. For example, Amazon.com’s formula to calculate sales tax does not depend on whether a user orders a book through their browser, in the Amazon mobile app, or from their Kindle.
Persistence
The domain logic depends on the persistence logic to store and retrieve data.
Persistence logic is responsible for managing the underlying state of an application. The name persistence refers to saving information so that it is not lost when a computer restarts (i.e., the data is persistent).
Most commonly, the persistence layer is responsible for communicating with the database. In a typical web application, the persistence layer is responsible for the following services:
-
Creating, reading, updating and deleting database records
-
Establishing a database connection
-
Reconnecting to the database when a connection is lost
-
Translating between the format of database records and higher-level objects used in the application
-
Communicating with other low-level data storage systems (messaging systems, transaction managers, legacy systems)
Why layer?
Whether or not to use these three layers is up to you as a developer and software designer. There is no legal or technological requirement to use these layers. However, the three-layered architecture is a proven strategy for structuring web applications.
By structuring your code around these three layers, you will help isolate parts of your application that evolve at different speeds:
-
The presentation layer separates your domain logic from the rapid changes in end-user interface technology. It protects the domain logic from rewrites when, for example, switching from React to Angular, adding a public API, creating a native iOS/Android app, or updating the graphic-design.
-
The domain logic tends to evolve slowly, with business requirements. When domain logic is in a separate layer, business changes are isolated from the technology changes that occur in presentation and persistence logic.
-
The persistence logic helps protect the domain logic from changes when the application scales and grows. It is easier to switch databases (e.g., from a MySQL database to a PostgreSQL database) or deploy a sophisticated database cluster when persistence is separate from the domain logic.
Adding additional layers
The three layers are widely understood. However, in practical situations, developers may choose to add additional layers as implementation details.
For example, if you are building a web application with React or Angular, you might insert two additional layers to manage the communication between your browser and the server. The result is a five-layer architecture:
Client-side / browser layers |
1 |
Presentation |
2 |
View model / API client |
|
Server-side layers |
3 |
API |
4 |
Domain |
|
5 |
Persistence |
In this five-layer architecture, the presentation layer uses a local view model that runs in the browser. The view model encapsulates all the details about communicating with the server, such as using HTTP and setting the correct authentication cookies.
On the server-side, the API serves as the public interface to the domain logic. The API is responsible for translating incoming requests (e.g., sent in JSON format) into function calls in the underlying domain logic.
Other refinements of the three-layer architecture are possible. For example, Martin Fowler [2] divides the domain logic into service, domain object and data access layers, which respectively implement units of work, individual entities and the translation of entities into database storage.
Using layers
Software architecture is not a fixed set of rules. There are many ways to implement the design principle.
To get started with the three-layered architecture, identify the parts of your code that correspond with each layer. Once you have identified those layers, you can restructure the project, to ensure each layer’s code appears together but separate from other layers.
The specific technical structure for separating layers can vary. Some possibilities are as follows:
-
Each layer in a separate function
-
Each layer in a separate file
-
Each layer in a separate directory
You may also choose to identify the layers by name. If you like the formal names, you could name these layers presentation
, domain
, persistence
. If you prefer shorter names, you could name the layers like ui
, api
and db
[3] (or fe
, be
and db
[4]). The names are up to you.
As you continue to develop your application, these layers will evolve. Sometimes you may even decide to shift some logic between layers. For example, the currency symbol ($) might be hard-coded into the presentation logic on a simple web store. However, as the store grows to serve an international audience, this logic may be moved to the domain logic to support sales in foreign currencies.