We start our journey through software architecture patterns with one of the most common. The layered pattern is easy-to-use and often easy to understand. However, it is misunderstood, and there are challenges to overcome. These are not weaknesses of the pattern. Instead, they are obstacles for the designers and implementors to overcome. This approach is also known as an N-tier pattern.
The Layered Pattern Defined
This pattern is a divide-and-conquer approach to software architecture. The application is broken down into four layers that interact. Thus, a complex problem to be addressed as smaller problems. The four layers typically flow from the user to the solution’s back-end.
- Presentation Layer/User Interface
- Application Layer (sometimes called service)
- Business Logic Layer
- Data Access Layer (persistence)
Note that the pattern allows for three or more layers. Then, they can be further broken down to ease implementation.
Tackle The Smaller Problems
This pattern is simple to understand. First, you break up the solution into functional areas. There is at least a user interface (presentation), business logic, and a data store. These layers can be split into smaller modules for large systems. That makes the implementation less complex and assists in assigning resources.
For example, the UI can be split into display and UI logic like CSS and UI functions. We see this often in React, Angular, and similar modern solutions. The business logic is split into general rules and data manipulation functions. Finally, the persistence layer may be a front-end that can be designed to point to different back-end systems.
The best part about this pattern is that the layers can be abstracted from each other. That may seem a small thing. However, it can be invaluable as systems age, and new platforms become available. One of the best examples is the move to mobile devices and smartphones in recent years. The presentation layer is often very different for these smaller and less powerful devices. That can require an entire rewrite of the system when there is too much overlap and interdependencies among layers.
While it seems simple enough, the determination of which code belongs in each layer can be a challenge. There are often functions that touch multiple layers. Thus, the placement of those must be designed intentionally. Problems arise when the design process is short-circuited. That leads to cross-functional modules that are not properly designed. Therefore, questions should be asked regularly about where code and functions belong. That attention to detail can be the difference between proper execution of this pattern or falling into an anti-pattern.