When someone talks about creating tiers or layers in an
application’s design they are referring to grouping code based on their
higher-level concerns. The most common and basic approach is to make three
groupings of code: Presentation Code, Application Code, and Data Access
code. All code that has to do with presenting information to a user
is in the Presentation Code, all code pertaining to the application itself
(logic, brains of the system) is in the Application Code, and finally all code
related to accessing a data store is in the Data Access code. I may
be starting to sound like a broken record, but the purpose of the layers is to
maintain a separation of
concerns. This separation is also enforced in a hierarchal manner
in that coupling between the groups of code is just one way. This
means that the Presentation Code references and calls code in the Application
Code, but the Application Code does not reference or call code in the
Presentation Code. The same goes for the relationship between the Application
Code and the Data Access Code. And finally, the Presentation Code knows nothing
at all about the Data Access Code.
Whether we refer to a grouping of code components as a tier or
a layer depends on exactly how the code is being separated.
When code groups are placed in different projects or systems where only the
public interfaces are exposed to each other, then we would say the code is
physically separated, each in its own tier. When the code groups live
in the same project and separation is provided by naming conventions, folders,
or some other coherent way then we would say the project is logically
separated, each in its own layer. It helps me to think of a cake where
layers sit right on top of each other, but tiers are physically divided by
plates and columns.
Presentation Layer/Tier
AKA: Front End, User Interface Layer, GUI (Graphical User
Interface),
The presentation layer code is concerned with providing an
interface for a user to work with the application. This code needs to be able
to get information to a user and be able to collect information from a user.
That is the extent of its purpose, its concerns. The actual “smarts” of the
application, otherwise known as business logic, is not mixed with this code.
For example, the presentation code may know that we need to allow the user to
choose 2 accounts and a dollar amount in order to try to transfer money, but it
has no idea how the transfer actually gets done, or what makes the transfer
valid, etc. The benefits to this design are all the benefits you get from a separation of
concerns, namely code that is easy to understand because it only deals
with one thing (user interface interaction).
Application Layer/Tier
AKA: Business Layer, Domain Layer, Middle Layer
The application layer is full of code concerned with capturing
the business of whatever domain the software is representing. This layer is the
heart of the application, hence the name application layer. If the
presentation layer only knows we need two accounts and a dollar amount to
attempt a transfer, then it is the application layer that does all the heavy
lifting involved with the actual transfer. For example, this layer might
determine the accounts available for transfer, validate that the dollar amount
is acceptable, actually coordinate moving money from one account to another,
etc.
In an object-oriented or object-based design the application
layer code is captured in what is commonly called business objects and or
application services. Although it is clearly not the only benefit, a properly
built application layer could have any kind of presentation layer put on top of
it. For example the same application layer can have a Windows-front-end and or
a web-front-end without changing anything about the application layer.
Data Access Layer/Tier
AKA: Persistence Layer, Data Management Layer, Data Layer
Often this layer is referred to by its abbreviation DAL. The
data access layer is full of code concerned with Creating, Reading,
Updating and Deleting data, otherwise known as CRUD. This layer works directly
with a data storage device (most commonly a relational database system like
Microsoft SQL server or Oracle database server.) As with the other
layers, it knows nothing of the layers “above” it. The DAL is an independently
working system with the singular focus of data CRUD.
Beyond the basic 3
Often within the three basic tiers there are layers that are
logically divided and placed in one of the tiers. For example, the data tier
might return object’s specifically designed for transporting and stepping
through data. Examples in the .Net world would be a DataReader or
DataTable. In the business tier we need to be able to take one or
more of these data transfer objects and convert them into a business object. We
don’t want to concern our business objects with this as it has nothing to do
with the business. So a Data Translation layer may be created with classes that
handle reading these data objects and putting the data into the correct
business objects.
Data Translation Layer
(AKA: data mapping layer)
This layer of code bridges the gap between the data access layer
and the application layer by translating data returned from the dal into
objects in the app layer. Because of the tiered architecture and a separation
of concerns, the domain objects know nothing of database technologies like
RecordSets, DataReaders, and ResultSets. However, the code in the data
translation layer does and is then responsible for taking data from these data
structures and creating objects. This layer is for resolving what is often
referred to as the impedance
mismatch between relational databases and object oriented design.
Application Services Layer
AKA: Business Services Layer, Control Layer
This layer of code provides an interface for encapsulating
processes the application completes. This is a thin layer of code that has no
business logic aside from knowing what steps a process has or what is required
of the process. All the thinking, the hard stuff, is left to other code, namely
business objects. The interface to the service layer objects are
sometimes referred to as a façade since it provides a simplified
interface to what might actually be communication amongst many other objects.
For example, the process of logging a user in to an application
might require looking up a user object, validating a password, logging the
login attempt, checking system access status, etc. However, this might simply
require one call from the presentation layer to the LoginService. The
methods in this layer often map directly to use-cases, user-stories, use-scenarios,
requirements, etc. In other words, the public service methods often read like
an abstract summary of what a system can do. Not only that, they are written in
the language of the users and or business analysts. For example, a system might
require someone to transfer money from one account to another. An Account
Transfer Service would probably have a method called Transfer. If we looked
behind the scenes of that method we would see the steps that are required:
check security, validate amounts, transfer in, transfer out, log the event, and
respond with completion message. The service knows what these steps are,
but not how they are accomplished.
User Interface Controller Layer
The UI controller layer sits between the presentation and
application layers. This layer is often used when the user interface is
disconnected, like with a web application or is distributed onto a computer
that is separate from the computer the application layer is on. Its purpose is
to help facilitate communication between the layers without corrupting either
layer. For example, imagine a user interface that requires four calls to the
application layer to get all the information it needs to display itself
correctly. On a desktop application we would not think twice about making those
four calls. However, if all those calls were to an application layer sitting on
a different computer (as is often the case with websites and other distributed
applications) we might be rightfully concerned with the speed at which these
things will get done. We might want to make only one call that
collects all the data together and maybe even converts the data into XML/JSON
or some other structure that makes it easy to pass across the network. Making
the four calls and massaging the data as needed for the UI would be this
controller layer’s job. This layer is often considered part of the presentation
tier, but it lives on the same machine as the application layer so it has
instant access to the application code.
System Layer
A system layer contains code, often in the form of libraries
that provide wrappers to common system needs exposed in common and an
easy-to-use ways for our application. For example, there might be 6
classes and 12 different ways to read and write text files to the hard-drive in
your programming language’s framework library. A system layer
library could expose a façade with two methods for the most common needs your
application might have: ReadTextFile and WriteTextFile. When the new version of
your framework is released and a class is deprecated or a new more efficient
way to do something is released, our changes to how we do these common things
are encapsulated and changed in one place. One example system class I often end
up with is a StringLibrary class that has all the common functions I find I
could use but are never provided like trimming a string that might be null,
making a collection of strings into a readable list (Jakson, Miller, and Steve),
check if string only contains letters, make first letter uppercase, removing dangerous
JavaScript characters etc.