Onion architecture is a great fit for microservices for a number of reasons. Firstly, it allows for each microservice to have its own database which acts as a data access layer. This means that each microservice can be completely independent and decoupled from the others. Secondly, it also allows for each microservice to have its own http client. This means that each microservice can communicate with the others without having to go through a centralised point. This makes for a much more scalable and flexible system.
- The Service layer is split into two projects, Services.Abstractions and Services.
- There can be external layers which are called presentation layers or testing layers.
- They could also change their database vendor, their ORM layer, or even go from a relational database to a NoSQL solution.
- However, if you require an architecture analogy, you slice it horizontally through the center.
- The drawback of this traditional architecture is unnecessary coupling.
- If a process or domain layer couples itself with infrastructure concerns, it is doing too much and becomes difficult to test.
These also form basis for the architectural patterns that are explained later. Standardized interfaces between layers usually confine the effect of code changes to the layer that is changed. You may require to add the reference of Domain Layer in your repository or other projects. One other problem with n-tier architecture is its nature to create tightly coupled layers and this may lead to deployment complexity. Nothing in an inner circle can know anything at all about something in an outer circle. In particular, the name of something declared in an outer circle must not be mentioned by the code in an inner circle.
Brief Overview of N-Layer Architecture
You can see the clear separation of concerns as we have read earlier. Maybe an Entity Framework Core Layer for Accessing the DB, a Layer specifically made to generate JWT Tokens for Authentication or even a Hangfire Layer. You will understand more when we start Implementing Onion Architecture in ASP.NET Core WebApi Project. This layering can help in the separation of concerns, subdividing the solution into smaller units so that each unit is responsible for a specific task and also takes advantage of abstraction. For mid to larger scaled projects where multiple teams work, layering has very obvious advantages up its sleeves. It lets a specific team or individual work on a particular layer without disturbing the integrity of the others.
Another difference between the two architectures is the way they handle technical concerns. Clean Architecture places a particular emphasis on using interfaces to decouple components, allowing components to be easily swapped out or replaced. It’s just a simple Onion Architecture with CQRS and Event Sourcing. You can use it as you want, you can create a GitHub repository using the template from there or just doing a fork/clone and creating the template from the dotnet CLI. Just wanted to share a simple approach for Onion Architecture that has saved me a lot of time engaging productivity for everyone on my team.
Middleware in ASP.NET Core
One may replace Application Services with Use Cases/Ports if it better suites the application. One may split Domain model into Domain Entities/Domain Services as well. Such as Spring has grown as DI framework/IoC container (and then suddenly grown into swiss knife of java world but who cares). RxJava is designed to account for the reactive programming.
The goal of this separation is to increase code reusability and decrease coupling between the different parts of the application. As we can see, there is a bunch of translation from top to bottom and from bottom to top going on. As long as only data is transferred the mapping process is tedious but manageable. As soon as the presentation layer would like to reuse business rules from the core domain model this approach’s drawbacks outweigh its benefits. Instead of getting the best out of the benefits of the layered architecture style, we end up with several layers dependent on the layers below it. For example giving the previous layering structure the presentation layer depends on the application layer and then on the domain layer and finally on the database layer.
CQRS Pattern — C#
The actual type of database and the way of storing data is determined at the upper infrastructure level. In the case of the API presentation layer that presents us the object data from the database using the HTTP request in the form of JSON Object. But in the case of front-end applications, we present the data using the UI by consuming the APIS. Now we need to add a new project to our solution that will be the service layer. It can receive objects that implement some known interfaces (dependency injection), and it’s allowed to import entities from the Domain Layer.
This is also known as DIP or Dependency Inversion Principle. To me, the essence of Onion Architecture is the application of Dependency Inversion Principle with architecturally defined priorities between layers. And finally, we saw how our Presentation layer is implemented as a separate project by decoupling the controllers from the main Web application. Then, we explained how we can connect all of the layers using an ASP.NET Core Web API.
Adding Swagger To WebApi Project
I’m intentionally ignoring infrastructure here because this typically varies from system to system. We often don’t keep systems up-to-date because it’s impossible to do. If coupling prevents easily upgrading parts of the system, then the business has no choice but to let the system fall behind into a state of disrepair. This is how legacy systems become stale, and eventually they are rewritten.
This means that each microservice has a well-defined set of responsibilities and a clear boundaries. This separation of concerns allows for a more scalable and maintainable architecture. The application layer stands between the domain layer and the infrastructure layer.
The application’s entrypoint — dependency injection
Business Logic is probably the most important part of this entire setup. It holds all the logic related to the Business requirements. Now, every application ideally has its own dedicated Database. In order to access the onion layer architecture Database, we introduce a Data Access Layer. This layer usually holds ORMs for ASP.NET to fetch/write to the database. When there is just a logical separation in your application, we can term it as layers or N Layers.
Let’s understand different layers of the architecture and their responsibilities with an order creation use case. Application is divided into layers where each layer has a set of responsibilities and addresses separate concerns. Each layer acts as modules/package/namespace within the application. Now we’ve seen the types of layers there are and what they’re used for. The most important piece is to start using some of these lessons to build your systems. And you’ll be more comfortable with pulling things out in ways that make your code more modular and maintainable.
Avoiding Repository pattern – implementing Onion Architecture with DbContext only
And let’s say that our system requires the ability to retrieve an order by order number. The domain defines the concept of an order and an order number. Additionally, It defines the interface for this behavior. Now the actual data access implementation itself exists in the outer layer. And it doesn’t matter if this implementation involves a database repository, a file system, or a guy named Stan who types out the order details from memory. For example, in a simple three-tiered architecture, the UI layer couples with the service layer and therefore the database layer.