Represent every system, subsystem, and application using a single and unified three layer architecture, regardless of its nature and role in the entire system or solution.
I have seen many different software solutions, consisting of numerous different applications. With each application, I expect to see a single and unified architecture followed, but unfortunately that's not the case. Different applications often go their own ways by inventing yet another layering structure. Sometimes this simply means that layers have changed names, but mostly it means that I can't even relate the final architecture to the simple 3 layer application architecture.
This kind of diversity often results in
Based on these findings, uncommon architectures should be avoided, unless absolutely necessary (which is almost never necessary).
There is definitely a need for the unified and common architectural layers, regardless of the kind of the application or system at hand.
I don't need to go too far to look for the right answer. In most (if not all) cases, it's absolutely sufficient to follow the famous 3 layer software architecture. These layers are:
Let's add couple of more guidelines to each of the layer.
Presentation layer is not just a user interface - it is an interaction point. Not just for the humans like you and me, but also for other applications that need to interact with the system at hand. e.g. for services, presentation layer is their service and operation contracts; for console applications it will be the console screen and functions to read from or write to the console. Whatever we expose to the outside world, that must be called Presentation. Some people associate this name with the user interface and so they would argue about the correctness for using this term here. But in my mind, it sounds absolutely fine, as it's something that we want to Present to the consumers of our application, be it a human or a machine. Presentation layer fulfills received requests and interactions by routing calls to the next layer - Business Logic. It could also invoke other systems or applications to fulfill the needs existing in the presentation layer itself. Interestingly, presentation layer of the current application interacts with other applications through their presentations layers - since it's the only layer for the consumer interaction.
Business Logic is usually a set of class libraries (or just classes and functions) containing domain models and other knowledge around the business, expressed in the current programming language. Other applications or systems don't directly interact with the business layer of the current application, since it's an implementation detail, standing behind the presentation layer (which is what is being exposed to others). Business logic layer in turn can interact with the next layer - Data Access. It could also invoke other systems or applications to fulfill the needs that exist within the business logic layer itself. Interaction with other applications or systems happens through their presentation layers only.
Data Access is where we persist data for the application or system. Other applications or systems don't directly interact with this layer. If they do want to do so, we have to expose such interaction points through the presentation layer. Data access layer sometimes will need to interact with other applications or systems to fulfill the data persistence related needs. This interaction should be happening by interacting with the presentation layer of the invoked applications or systems. e.g. we can connect to another service (through its presentation layer - service & operation contracts) to persist the data, instead of connecting to the database.
This may sound quite a lot to digest, but the guidelines are very simple and straightforward. Using those, we can construct an entire system of any complexity - either very simple or very complex. We will look at an example soon.
To summarize, these are the final guidelines we agreed on:
Suppose we have a Single Page Application (SPA), consisting of UI, Web API, and Database. Web API calls into two different services for various purposes.
Below I will try to prove that every system represented in this example has the 3 layers in it.
Many people mistakenly think of UI, Web API and Database as the layers of the application. While they do make sense to be the tiers (or even entirely separate applications), not all three of them could be considered as layers. e.g. Web API is not a layer, because inside Web API, we typically have layers of their own, such as HTTP request handlers and controllers (which I call Presentation), business logic, and data access. So, at least it's not hard to agree that the Web API does come with the 3 layers I'm talking about.
For the sake of the example, our Web API is using two different services. Service #1 is used from Business Logic to fulfill some of the domain layer's needs, while Service #2 is from Data Access layer to store specific kinds of data in it. (By the way, I recently wrote an article about distinguishing between Data Services and Business Services. So, in those terms, Service #1 would be a business service, while Service #2 would qualify as a data service.)
As we spoke before, both the services used from the Web API have similar layering structure, including service and operation contracts (that handle requests and responses), business logic and their own data access as well. Indeed, most of the services we invoke will already have all these layers, as they are considered to be a fully functional application that the clients can interact with.
For the sake of the argument, Database can also be split into layers, which I'll leave without further explanation, since I believe you have understood the point of this conversation.
Conclusion - everything comes in three layers.
While I was writing this article, I realized that I have written couple of others somewhat related to this topic. They don't quite repeat the subject, but they do support the thoughts expressed here. I guess that means my beliefs are as strong as before, and they don't fluctuate much. In other words, everything together makes sense.
Here are the related articles that I found:
Layering Software Architecture - speaks about the same layers, but more from implementation details, such as to avoid coupling between business logic and data access layers.
Data Services vs. Business Services - speaks about different kinds of services, which is related to my example above - using two different services - one from business logic and the other from the data access layer.