Onion Architecture: A Guide to Clean and Sustainable Code

Let’s consider the use case to create an order with a list of items. We first need to calculate the price including tax computation/discounts, etc., onion architecture save order items and send order confirmation notification to the customer. The application services can be only invoked by Infrastructure services.

The idea is to keep external dependencies as far outward as possible where domain entities and business rules form the core part of the architecture. In this article, we will cover the onion architecture using the ASP.Net 6 Web API. Onion architecture term is introduced by Jeffrey Palermo in 2008. Onion architecture solves common problems like coupling and separation of concerns. Onion Architecture is a software architectural pattern that promotes a modular and loosely coupled design, focusing on separation of concerns and maintainability.

‘Ports and Adapters’ architecture. What is there?

This is possible thanks to the dependency rule that we introduced in the previous paragraph. Since no code in the application core depends on outer layers, we can just swap out the UI or the database for the testing (or any other) purposes. The domain layer lies in the heart of the Onion Architecture, representing the business and behavioral objects. All of your domain objects should be located at this core.

  • C# programmers are drawn to Onion Architecture due to the dependency flows.
  • Also, we’ve shown you the Presentation layer implementation by decoupling the controllers from the main Web application.
  • The application’s user interface is made up of views and controllers, and the presentation layer is responsible for managing it.
  • In onion architecture, we have the domain layer, repository layer, service layer, and presentation layer.

Clean code is simple to read, which facilitates debugging and modification. The modular and decoupled architecture that the Onion Architecture encourages makes it simpler to maintain the application over time. Developers can make changes to one layer without impacting the other levels since each layer has a distinct function and communicates with other layers through clearly defined interfaces. The “Onion Architecture,” a well-known software design, has a number of benefits for both businesses and developers. Some of the main advantages of onion architecture are listed below. Because modifications to one layer don’t affect the others, this separation of responsibilities makes code maintenance and updating simpler over time.

It’s never too late or early to start something

Today, we will discuss Onion Architecture which is also said to be a cousin of layered and hexagonal architecture. The web world is a collection of various traditional architectures. Each of these pieces of architecture has its pros and cons.

However, we are going to do something different from what you are normally used to when creating Web APIs. By convention, the controllers are defined in the Controllers folder inside of the Web application. Because ASP.NET Core uses Dependency Injection everywhere, we need to have a reference to all of the projects in the solution from the Web application project. This allows us to configure our services inside of the Startup class.

Generate the Migrations and the Database

I will just create a new product and make a request to query all the existing products as well. Just to make our solution a bit clean, let’s also add API Versioning to the WebAPI. With the CRUD logic out of the way, let’s set up EFCore in the Persistence Layer and try to generate a database.

So, this article defines only the fact that every single external boundary is referencing and application instead of application referencing external boundaries. This way we achieve application robustness as any of the boundaries might be replaced by re-implementing ports or adapters. Jeffrey Palermo describes layered architecture in his initial article introducing term ‘onion’. One of such choices is the decision about the code, highly reused by whole application including the domain objects. There are architectures like clean, hexagonal and onion with the same objectives and some differences in their implementation.

Cumbersome when you don’t have many business rules

In this article I am approaching this task in layered, onion and ports and adapters architectures. I will start from the layered architecture (which is considered being outdated nowadays) and make a transition into more modern onion and ports and adapters. The purpose of the article is to eliminate an uncertainty while answering to “where should I place my commonly reused code? On the other hand, both Onion and Clean architectures, with their emphasis on centralizing the domain model and clearly defining the flow of dependencies, fit better with CQRS. Both can easily handle different models for reads and writes, keeping the system decoupled and coherent. The traditional layered architecture is one of the oldest methods of structuring applications.

The idea is to have all of your domain objects at this core. Besides the domain objects, you also could have domain interfaces. Domain objects are also flat as they should be, without any heavy code or dependencies. As per traditional architecture, the UI layer interacts to business logic, and business logic talks to the data layer, and all the layers are mixed up and depend heavily on each other.

Domain Layer

Each layer/circle wraps or conceals internal implementation details while providing an interface to the outer layer. All layers must also supply information that inner layers can easily consume. The objective is to enhance coupling inside a vertical slice across layers while minimizing coupling across layers. The outer circle’s classes, methods, variables, and source code generally depend on the inner circle but not the other way around. Now we need to add a new project to our solution that will be the service layer. We will follow the same process for adding the library project in our application, but here we need some extra work after adding the project we need to add the reference of the Repository Layer.

Here, for simplicity, we just have two layers in the Application Core. To demonstrate a common folder structure based on Onion Architecture, let’s consider a hypothetical e-commerce application. To me, the essence of Onion Architecture is the application of Dependency Inversion Principle with architecturally defined priorities between layers.

Disadvantages of N-Layer Architecture

It basically has the models/entities, Exception, validation rules, Settings, and anything that is quite common throughout the solution. You can see the clear separation of concerns as we have read earlier. The Onion architecture was first introduced by Jeffrey Palermo, to overcome the issues of the traditional N-layered architecture approach which we discussed above.

Setting up the Controllers

It is also possible to create more layers of abstractions depending on application needs. E.g. for smaller applications that don’t have a lot of business logic, it might not make sense to have domain services. Regardless of layers, dependencies should always be from outer layers to inner layers. The Service layer holds interfaces with common operations, such as Add, Save, Edit, and Delete. Also, this layer is used to communicate between the UI layer and repository layer. The Service layer also could hold business logic for an entity.

Benefits of an Onion Architecture

Business logic can’t function if data access isn’t there. 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.






Leave a Reply

Your email address will not be published. Required fields are marked *