Software can be built up of layers. This article describes how layers could be structured. Each layer comes with different technology.
Software can be split up into 3 main layers:
The presentation layer is the visual part of a program. It is what the user sees.
The business layer is like internal, mechanical parts. It can model the functionality of a program, but it isn’t directly visible.
The data layer stores the data. It models functionality more passively: It does not really process anything. It just stores things.
The presentation layer builds upon the business layer with user interface technology.
The business layer uses the data layer to store the data.
Sometimes the presentation layer skips the business layer using the data layer directly, represented with the dotted line in the diagram above. This can happen when the business layer does not really add any functionality.
The data layer may be programmed with mostly fixed patterns in this architecture. The presentation layer is mostly patterns too. The business layer can have patterns as well, but it gets a little more creative. If anything special needs to happen, it might be put in the business layer.
The data layer models and stores the data. It might be built up of the following sub-layers:
It starts with the database. This can be a relational database like Microsoft SQL Server
, which structuredly stores the data into tables and relationships. But it could also be another type of data store: an XML
file, flat file or even just in-memory data.
The database might not be directly accessed by the rest of the code. It may go through an object-relational mapper (or ORM
), like NHibernate
. This ORM
would translate database records to objects called entities.
It could also be a different data access technology: a different ORM
, like Entity Framework
, or XML
files, or perhaps SqlClient
to execute raw SQL
onto the database.
Entity objects have properties, that map to columns in the database, and properties that point to related entities. NHibernate
needs mappings, that define which class maps to which table and which column map to which property.
The FluentNHibernate API
can help set up these mappings.
With all this in place, out come objects called entities, loaded from the database. These entity objects represent the functional domain.
NHibernate
might not be directly accessed by the rest of the code. The other code might talk to the Repositories
instead. You might see a Repository
as a set of queries. Each entity type could have its own Repository
. Next to providing a central place to manage an optimal set of queries, the Repositories
keep the rest of the code independent of NHibernate
, in case you would like to switch to a different data technology.
The Repository
implementations might not used directly, but accessed through interfaces
, so that we can indeed use a different data access technology, just by instantiating a different Repository
implementation.
The dashed line going right through the diagram above, separates the platform-specific part from the platform independent part.
The platform-specific part concerns itself with NHibernate
and SQL Server
. The platform independent part is unaware of the underlying storage technology. You may as well stick an XML
file under it and not use SQL Server
or NHibernate
at all.
This makes it possible, to program against the same model, regardless of how it is stored. This platform-independence, also helps deploy the same code to different environments like mobile, Windows or web.
The presentation layer is the visual part of a program. It is what the user sees. It can be split up into the following sub-layers:
The presentation layer calls the business layer, which contains the rules that surround the system. It feeds the business layer input from the user, and processes the output data for display on screen.
It is the Presenter
classes that talk to this business layer. The Presenters
together form a model of application navigation. Each screen might get its own Presenter
. Each Presenter
method represents a specific user action on that screen.
A ViewModel
would contain a specific subset of data: exactly the selection of data, that is shown on screen. In this architecture ViewModels
are a pure data objects, no logic. So they can be more easily used with different presentation technologies. These pure data objects can also be sent over the line without many surprises.
The Presenters
might delegate to a ToViewModel
layer, to translate the data and the results from the business logic to a subset of data that is shown on screen.
The Presenters
also delegate to a ToEntity
layer, to translate user input back to entity data, before passing it on to the business layer.
Presenter
classes combine several responsibilities around presentation.
They call upon the business layer to Save
, Validate
, execute SideEffects
. They initiate translation between entities and ViewModels
and might also execute security checks.
Because the Presenters
combine several responsibilities together, they can be called the Facades
or combinators of the presentation layer.
MVC
is the technology of choice in this architecture for programming user interfaces for web technology. In this architecture the MVC
layer builds on top of the Presenter
layer.
MVC
uses Controllers
, which are similar to Presenters
in that they group together related user actions and each user action gets a specific method.
Controllers
are quite specific to MVC
. An equivalent might not be present on other presentation platforms.
However, even on other presentation platforms, like WinForms
, it might be advisable, to have a central spot to manage calls to the Presenters
and showing the right View
depending on their results.
Requests from the web browser automatically make the right Controller
method go off. MVC
makes sure of that. Each method in a Controller
tends to get a URL
.
The parameters of a Controller
method can be URL
parameters. A parameter can also be post data. ViewModel
parameters are accepted by MVC
Controllers
. The ViewModels
and are built up from post data by MVC
automatically.
JJ.Framework.Mvc
might be used to send whole tree structures of post data over the wire to be correctly parsed by MVC
.
After the Controller
method is done, the view engine kicks in. The view rendering automatically goes off.
A view engine that might be used in this architecture is Razor
. It offers a concise syntax for programming Views
, that combines C#
with HTML.
Razor
has tight integration with MVC
. The view engine can use a ViewModel
as input, along with the View
template (*.cshtml
). The output is a specific piece of HTML
sent back to the web browser.
In WinForms
the Views
would be the Forms
and UserControls
. It is advisable that even if a View
can have code-behind, to only put simple code in it and delegate the real work to Presenters
.
The Razor
engine produces a piece of HTML
received by the web browser.
HTML
here can be replaced by the type of presentation output. In WinForms
it might be the controls and their data. But it can also be a generated PDF
file. Anything that can come out of a presentation technology might be considered a View
.
The dashed line going right through the diagram above separates the platform-specific part from the platform independent part.
The platform-specific part concerns itself with MVC
, HTML
and Razor
, while the platform independent part is unaware of which presentation technology is used.
That means that we can use similar logic for multiple presentation techniques, such as offering an application both web based as well as Windows or a mobile app.
What is business logic? Basically anything that is not presentation, data access or infrastructure, might be considered the business logic. It’s the rules of a system. It’s like the internal, mechanical parts. The business layer might be split up into the following things:
The business layer resides in between the data access and the presentation layer.
The business layer can use entities out of the data layer. These entity classes represent the domain model. But sometimes it would call repositories to execute queries.
The presentation layer uses the business layer for anything special that might be done. The business layer guards rules and such. Sometimes when something special is programmed in the presentation layer, it may be worth considering moving it to the business layer.
The business layer can execute Validators
that verify that the data corresponds to expectations.
The business layer can execute SideEffects
when altering data, for instance updating the date time modified or automatically generating a name for a new object.
The business layer would also be responsible for calculations.
One thing can be converted to another. Conversions might be found in the business layer. This could be for simple objects. But you might also convert whole trees and structures to another.
Enums
are like multiple choice variables. Some entities in the data layer might have corresponding enums
in the business layer. And some pattern-wise logic around enums
might be there in the business layer too.
Resource strings
can make texts in an app multi-lingual. These might be put in the business layer to translate terminology from the functional domain.
Setting default values when creating an entity might be done automatically by using a SideEffect
class. Those may be executed in the business layer.
Along with one entity, other entities might be deleted. Cascading
here means the deletion of related entities when a main entity is deleted. Cascading
can also mean unlinking some entities before deleting a related entity. In this architecture this might be done in C#
to make it extra visible that these deletions take place.
Sometimes there is code for cloning or copying an object or graph of objects. Code for this kind of cloning might be put in the business layer too.
Bidirectional relationship synchronization can keep the two ends of a relationship in sync. By setting the parent property, product.Supplier = mySupplier
, the child collection, mySupplier.Products
, will also be updated to include myProduct
. This mechanism can be made part of a business layer.
Calling the business layer can happen through Facades
. They would combine several aspects of the business logic, by calling Validators
, SideEffects
, Cascading
and other things in all a row. Facades
might provide a few main entry points into the business layer.
The Facades
may orient around the basic data operations: Create, Read, Update and Delete or CRUD
. This set of basic operations might not change much, keeping the interfaces
relative stable. But Non-CRUD operations might be added too.
A business layer might be platform independent in this architecture, so that the code can be used anywhere. When most things are built upon entities and repository interfaces, the business logic is relatively independent, which means that the magic of the software would be deployable on many platforms. Sometimes this might require specific API
choices, generic interfaces and in-house programmed API's
. These choices are inherently part of this software architecture.
The subdivision into data, business and presentation is quite fundamental in this software architecture. But there can also be additional layers, called perpendicular layers:
At the bottom you can see Data, Business and Presentation layers, laid down flat on their side. The perpendicular layers are rotated 90° and placed right on top of the main layering. That’s why these layers are called perpendicular.
The Framework layer consists of API's
that could support any aspect of software development, so could be used in any part of the layering. That is why it stretches right from Data to Presentation in the diagram.
Infrastructure is things like security, network connections and storage.
The infrastructure can be seen as part at the outer end of the data layer and part at the outer end of the presentation layer, because the outer end of the data layer is actually performing the reading and writing from specific data source.
However it is the presentation layer in which the final decision is made what the infrastructural context will be. The rest of the code tends to operates independent of the infrastructure in this architecture and only the top-level project would eventually determine what the context will be.
The infrastructure tends to be loosely coupled in this software architecture. Let’s take user rights management an example.
User rights management can alter the program navigation model in the Presenter
layer, adapting it to what the user is allowed to do.
In that respect the platform-independent presentation layer is dependent on the security infrastructure, which is a paradox. The reason the Presenter
layer is platform-independent after all, is that it communicates with the infrastructure using an interface
, that may have a different implementation depending on the infrastructural context in which it runs. This could be accomplished with a config file or dependency injection.
What’s meant with services in this architecture, is exposing business logic through a network interface, like the SOAP
protocol. A service may also expose a presentation model to the outside world.
Presenter
classes
decouple presentation from business logic so you have full flexibility in the presentation layer. Presenters
also decouple the presentation technology so it can be flexibly replaced. The repositories decouple the data technology. And the generic interfaces on infrastructure decouple the infrastructure. Everything is decoupled to keep our options open.
Here is a variation on this architectural layering, that might also sometimes be used: data and business in one layer. Benefit: Might be easier to understand. Downside: More likely for data access and business to get entangled.
Another alternative is: no repositories. But C# interfaces
for everything. Not bothering with what’s data or business or repository.
It would still keep things loosely coupled and separation of concerns would also stay intact.