Layered Architecture

This post is part of The Software Architecture Chronicles, a series of posts about Software Architecture. In them, I write about what I’ve learned on Software Architecture, how I think of it, and how I use that knowledge. The contents of this post might make more sense if you read the previous posts in this series.

Layering is a common practice to separate and organise code units by their role/responsibilities in the system.

In an object-oriented program, UI, database, and other support code often gets written directly into the business objects. Additional business logic is embedded in the behaviour of UI widgets and database scripts. This happens because it is the easiest way to make things work, in the short run.

When the domain-related code is diffused through such a large amount of other code, it becomes extremely difficult to see and to reason about. Superficial changes to the UI can actually change business logic. To change a business rule may require meticulous tracing of UI code, database code, or other program elements. Implementing coherent, model-driven objects becomes impractical. Automated testing is awkward. With all the technologies and logic involved in each activity, a program must be kept very simple or it becomes impossible to understand.

Eric Evans 2014, Domain-Driven Design Reference

What it means to be layered

In a layered system, each layer:

  • Depends on the layers beneath it;
  • Is independent of the layers on top of it, having no knowledge of the layers using it.

In a layered architecture, the layers can be used in a strict way, where a layer only knows the layer directly beneath it, or in a more flexible approach where a layer can access any layer beneath it. Both Martin Fowler and my own experience tells me that the second case seems to work better in practice as it avoids the creation of proxy methods (or even complete proxy classes) in the intermediary layers, and can degrade into the anti-pattern of the Lasagna Architecture (more about it below).

Sometimes the layers are arranged so that the domain layer completely hides the data source from the presentation. More often, however, the presentation accesses the data store directly. While this is less pure, it tends to work better in practice.

Fowler 2002, Patterns of Enterprise Application Architecture

The advantages are:

  • We only need to understand the layers beneath the one we are working on;
  • Each layer is replaceable by an equivalent implementation, with no impact on the other layers;
  • Layers are optimal candidates for standardisation;
  • A layer can be used by several different higher-level layers.

The disadvantages are:

  • Layers can not encapsulate everything (a field that is added to the UI, most likely also needs to be added to the DB);
  • Extra layers can harm performance, especially if in different tiers.

The 60s and 70s

Although software development started during the 50s, it was during the 60s and 70s that it was effectively born as we know it today, as the activity of building applications that can be delivered, deployed and used by others that are not the developers themselves.

At this point, however, applications were very different than today. There was no GUI (which only came into existence in the early 90s, maybe late 80s), all applications were usable only through a CLI, displayed in a dumb terminal who would just transmit whatever the user typed to the application which was, most likely, being used from the same computer.

1960s-70s - Layered Architecture - 1 tier

Applications were quite simple so weren’t built with layering in mind and they were deployed and used on one computer making it effectively a one-tier application, although at some point the dumb client might even have been remote. While these applications were very simple, they were not scalable, for example, if we needed to update the software to a new version, we would have to do it on every computer that would have the application installed.

Layering during the 80s and 90s

During the 1980s, enterprise applications come to life and we start having several users in a company using desktop computers who access the application through the network.

At this time, there were mostly three layers:

  • User Interface (Presentation): The user interface, be it a web page, a CLI or a native desktop application;
    • ie: A native Windows application as the client (rich client), which the common user would use on his desktop computer, that would communicate with the server in order to actually make things happen. The client would be in charge of the application flow and user input validation;
  • Business logic (Domain): The logic that is the reason why the application exists;
    • ie: An application server, which would contain the business logic and would receive requests from the native client, act on them and persist the data to the data storage;
  • Data source: The data persistence mechanism (DB), or communication with other applications.
    • ie: A database server, which would be used by the application server for the persistence of data.

1980s-90s - Layered Architecture

With this shift in usability context, layering started to be a practise, although it only started to be a common widespread practice during the 1990s (Fowler 2002) with the rise of client/server systems. This was effectively a two-tier application, where the client would be a rich client application used as the application interface, and the server would have the business logic and the data source.

This architecture pattern solves the scalability problem, as several users could use the application independently, we would just need another desktop computer, install the client application in it and that was it. However, if we would have a few hundred, or even just a few tenth of clients, and we would want to update the application it would be a highly complex operation as we would have to update the clients one by one.

Layering after the mid 90s

Roughly between 1995 and 2005, with the generalised shift to a cloud context, the increase in application users, application complexity and infrastructure complexity we end up seeing an evolution of the layering scheme, where a typical implementation of this layering could be:

  • A native browser application, rendering and running the user interface, sending requests to the server application;
  • An application server, containing the presentation layer, the application layer, the domain layer, and the persistence layer;
  • A database server, which would be used by the application server for the persistence of data.

2010s - Layered Architecture

This is a three-tier architecture pattern, also known as n-tier. It is a scalable solution and solves the problem of updating the clients as the user interface lives and is compiled on the server, although it is rendered and ran on the client browser.

Layering after the early 2000s

In 2003, Eric Evans published his emblematic book Domain-Driven Design: Tackling Complexity in the Heart of Software. Among the many key concepts published in that book, there was also a vision for the layering of a software system:

 

DDD_layers
Eric Evans 2003

 

 

  • User Interface

    Responsible for drawing the screens the users use to interact with the application and translating the user’s inputs into application commands. It is important to note that the “users” can be human but can also be other applications, which corresponds entirely to the Boundary objects in the EBI Architecture by Ivar Jacobson (more on this in a later post);

  • Application Layer

    Orchestrates Domain objects to perform tasks required by the users. It does not contain business logic. This relates to the Interactors in the EBIArchitecture by Ivar Jacobson, except that Jacobson’s interactors were any object that was not related to the UI nor an Entity;

  • Domain Layer

    This is the layer that contains all business logic, the Entities, Events and any other object type that contains Business Logic. It obviously relates to the Entity object type of EBI. This is the heart of the system;

  • Infrastructure

    The technical capabilities that support the layers above, ie. persistence or messaging.

 

Anti-pattern: Lasagna Architecture

lasagna

Lasagna Architecture is the name commonly used to refer to the anti-pattern for Layered Architecture. It happens when:

  • We decide to use a strict layering approach, where a layer only knows about the layer immediately below it. In such case, we will end up creating proxy methods, and even proxy classes, just so we go through the intermediate layers instead of directly using the layer we need;
  • We lead the project into over-abstraction in an urge to create the perfect system;
  • Small updates reverberate through all areas of an application, for example, tidying up a single layer can be a large undertaking with huge risks and small payoff.
  • We end up with too many layers, which increases the complexity of the overall system;
  • We end up with too many tiers, which both increases the complexity and damages the performance of the overall system;
  • We explicitly organise our monolith according to its layers (ie. UI, Domain, DB), instead of organising it by its sub-domains/components (ie. Product, Payment, Checkout), destroying modularity and encapsulation of the domain concepts.

Conclusion

Layered Architecture is one more way to provide for separation of concerns, encapsulation and decoupling, by grouping code units by their functional role within the application.

However, as most things in life, too much is counter productive! So the rule-of-thumb is: Use just the layers we need, the tiers we need, and nothing more! We must not get carried away chasing an architectural holy grail, which does not exist. What does exist is a need, and the best possible fit for that need. Which is part of Lean, btw.

Furthermore, it’s important to note that this top/down approach to layering is outdated. It is no longer what we should do in modern software development, there are new and better ways of thinking of an application layer. I will talk about then in following posts.

Sources

2002 – Martin Fowler – Patterns of Enterprise Application Architecture

2003 – Eric Evans – Domain-Driven Design: Tackling Complexity in the Heart of Software

2011 – Chris Ostrowski – Understanding Oracle SOA – Part 1 – Architecture

11 thoughts on “Layered Architecture

    1. This comparasion has many layers (pun intended) as MVC as we know today with frameworks like Rails or Laravel, actually has almost nothing to do with MVC they are closer to the 3-layered architecture showed in the post.

      The first thing to notice is that MVC is more like a design pattern than an architecture, at least in the way it was originally conceived in Smalltalk. The original MVC described by Trygve Reenskaug wasn’t even popular in production, so there’s almost none record of what MVC as described in the original paper should be like, what is actually proper recorded by history was the “framework” version called MVC Smalltalk-80, that was objects implementing the pattern, available on Smalltalk-80 standart library for desktop ui programming (kinda like Swing objects if you ever used Java).

      In Reenskaug original idea we actually had 5 concepts: Model, View, Editor, Controller and Tool, but to understand this we have to understand what were the 3 main responsabilities of the MVC abstraction.

      One thing that is consistent over all iterations of MVC (even its derivated patterns like MVP or MVVM) is that you are concerned with 3 problems:

      UI
      Data
      Input

      The idea is that you have an model that represents your data (the concept of domain didn’t existed at the time, but probably would go here too since these should represent your business objects), a view that represents the the various representations that the data in the model could have, displaying them for the user that in turn would interact with the UI and send some form of user input to the application (like click in a button, select a text or use the keyboard), update the model, which, in turn, would notify the view to update itself.

      Notice that for the last concern, the user input, i didn’t mentionated any specific object that was responsible to handle it, well, that its because this is the part were MVC (and all its family) becames confused.

      In the original Reenskaug MVC, user input could be handled by View, Editor, and Controller. The difference is that View and Controller always forms a pair that is called a Tool, which in modern terminology would be something similar to a component or a widget.

      View could handle some inputs by itself, much like if the event only concerns the view and should just update that view, then its coupled in the view.

      An Editor would be an special object that view would instantiate to handle these user input, so, in the case that i mentionated in the last paragraph, probably the view would create an editor, and then use it to handle user input, and update itself, or notify the model for events that only occour and affect that view.

      A Controller is an object that manages the creation of the View and its sub-views, much like you don’t create just a div, you create a div with something inside, like a button, so the Controller was the one that managed the creation of these view objects. It also handled the events that affects at Tool level, so if some View triggers and event, but the update on UI needs to be spread over some views inside the Tool, the Controller handles each view to update accordingly to the event triggered.

      Well, all of this was the original MVC, but since we lack historical records about this form of MVC outside Reenskaug himself, i guess just him used MVC this way.

      So what we could actually consider the true form of MVC that is what people who programed in MVC and all the further literature over the subject is based upon is the Smalltalk-80 MVC, that was one version made for the people who worked in MVC together with Reenskaug but this time they implemented their version of the pattern directly in the standart library of the Smalltalk.

      Here the things properly took shape and we actually have extensive historical documentation and code examples about it. Which simplify things a lot, basically this version of MVC actually is formed by MVC (since Reenskaug version was made by Model View Editor and he himself acnowledges that), here the Controller took the role of the Editor, so the Editor is now called Controller, and the original Controller was gone, which simplify the things to be just a Tool (View + Controller/Editor) + Model.

      So now you have a model that is an observer, which is observed by an view to retrieve its data, so every time the model changes, the view updates itself automatically (like in modern JS frameworks but in a very rudimentary way), and as part of a controller that receives user input, calls methods on model, which in turn updates the view.

      Notice that we just have a triad of objects, but they are components of each other, with circular dependencies, so there’s no such thing as a view layer or a controller layer, since the view (tool) is made by an view and a controller together).

      The 3 layered architecture actually is a layered architecture, which is divided in Presentation, Domain, and Data.

      Notice that while we have Presentation that is roughly equivalent to a View, and Data that is roughly equivalent to a Model, Domain and Controller don’t have anything to do with each other.

      The concerns here are different we aren’t trying to make an architecture to UI, we are trying to make an architecture for the whole application, so the user input concern is bundled in the Presentation, so the Presentation actually corresponds to View + Controller in MVC, and the contrary occours in the Domain and Data layers, where they in MVC they are collapsed in the Model.

      When MVC came to the web much thanks to Java Model 2, and actually as MVC in Rails, the objects were now properly separated in layers and had their responsabilities recontextualized to:

      Database (Model)
      UI (View)
      HTTP (Controller)

      And if you notice something missing here its because is missing, if we go back to the 3 layered architecture, we have the Presentation layer represented, again, by the View + Controller combo (that made a full 360º back to the original Reenskaug separation since the view handles all the user input, and the controller handles the creation of the view), and the Data layer represented by the Model, but we don’t have a place anymore to put the domain layer.

      So this gave birth to one of the biggest mistakes in “OO” architecture, the idea very common of separating the “MVC” application like an 3 layered architecture but using the MVC names mixing both architectures names and concerns.

      The famous Controller Service Repository “MVC” flavor where you have an Controller (that isn’t a controller since it handles http layer not user events), an Service Layer (that isn’t a service because its just a procedural layer to put the domain logic separated from the business objects, breaking encapsulation completely), and an Repository layer (that isn’t made of repositories, its actually formed by DAOs).

      Like

    1. Cool.

      Keep in mind though, that this is an “old” architecture style for building applications. Although it might still be useful to use in some cases.

      Now days, for building big and complex enterprise applications, we are better off using domain centric styles like what i explained in later posts.

      Liked by 1 person

  1. You should check out Onion Architecture. I think there are some subtle differences. Instead of data driving design, it’s the application domain. Works out really well.

    Like

Leave a reply to hgraca Cancel reply