Creating a layered application
When we talk about application layers it is in reference to the logical grouping of functionality/components into separate layers that communicate with each other and with other applications. Layers refer to strictly the logical grouping of functionality and not their physical deployment location (tiers).
In most cases several layers of your application will reside on the same tier.
No matter what type of application you are designing you can decompose the design into logical groupings of software components, otherwise known as layers. Layers help to differentiate between the different kinds of tasks performed by the components, making it easier to create a design that supports reusability of components and greatly increases the maintainability of the code.
At the most abstract level an application will typically be divided into three layers: Presentation, Business & Data layers. Below is a picture of what this common three layer architecture would look like.Presentation Layer
- The presentation layer is the UI centric layer, it provides the 'view' of the application to the client. In a typical web application this would be the resulting html that is sent down to the browser. This layer provides the interactive access to the application and to the end user this is the most important (only visible) part of your application.
Service Layer (not pictured)
- When your application must provide services to other applications, as well as implementing features to support clients directly, a common approach is to use a services layer that exposes the business functionality of the application. This layer is commonly located between the presentation and business layers.
Business Layer
- The business layer implements the core functionality of the application. It is the place where all of the business logic is encapsulated.
Data Layer
- The data layer provides access to the underlying datasources (i.e. databases, services, etc.) and exposes this data through defined interfaces for the business layer to consume.
When developing within different application layers you need to decide how each layer will communicate with each other. The two most common patterns for layer interaction are:
- Higher level layers can interact with layers below, but a lower level layer should never interact with layers above. Using this approach will help you avoid circular dependencies in your solution. A common way for higher level layers to be aware of lower level layer changes is through an eventing mechanism.
Top-down InteractionStrict Interaction
- In this model each layer may only interact with the layer directly below it. This layer enforces a strict separation of concerns since each layer is only aware of the one immediately below it. The benefit of this type of rule is that any changes made to a layer will only affect the layer directly above it. This type of design makes the initial development a little more rigorous but can pay off over time when changes need to be made.
With the use of some data access tools such as ORM frameworks the line between the business layer and data layer is blurring. An example of that is when your business entities that contain all of your business rules is also a data-aware entity.
If the business entity is data aware that could mean that simply touching a property on the object will result in a query being executed against the database. Using the classic 'Customer' object as an example if there was an application view that displayed a customer and their orders, your presentation layer may have access to the 'Customer' object from the business layer. In turn when the view goes to display the customer's orders, likely through a property such as Customer.Orders, the underlying ORM framework will run out to the database and fetch the related orders.
This isn't necessarily a bad thing, it is however something that you need to be aware of and create your design in such a way that this is acceptable or not. One common pattern for solving this issue is to make use of the ViewModel approach where your presentation layer gets a 'dumb' object that has only the data necessary for display and can't cause any behind the scenes data access to occur.
After defining the layers of your application you need to define the functionality that spans multiple layers in the application, these types of functionality are commonly referred to as crosscutting concerns.
Some common crosscutting concerns are: logging, caching, validation, exception management, etc.
Once you have identified these concerns you can create separate components that can then be reused within each layer of the application that requires that functionality.
Avoid mixing the crosscutting code with code in components of each layer, so that the layers and their components only make calls to the crosscutting components when they must carry out one of those actions.