Onion Architecture

I will try to explain what Onion Architecture is, pros and cons and implementation example.
 
So first of all software architecture's like a blueprint for both the system's behavior and the mechanisms used to achieve that behavior.
Architecture provides structured approach to managing complexity of software systems. It supports scalability, maintainability and flexibility by defining patterns and practices, making it easier to understand, promoting code reuse and adapting to changing requirements.
 
Origins of Onion Architecture
With commonly used traditional layered architecture, each subsequent layer depends on the layers beneath it. This creates thight coupling, makes it challenging to replace, upgrade or adapt changes without affecting all layers. (As Palermo says when explainin this arch.: "However, without coupling, our systems wouldn’t do anything useful, but this architecture creates unnecessary coupling.")
 
 With this architecture, dependency/coupling is towards the center. All code can depend on layers in the center but can not depend on layers further out.
 
Onion Architecture

Number of layers may vary depending of the application but domain model is always at the core. Domain model is not coupled to anything but itself. 

Domain Services layer holds domain/object related interfaces.

Application services layer implements use cases. These services interact with other services to achive the client’s request. As i said earlier coupling is only is towards the center so the application services can be only invoked by outer services, not from inside.

The outer layer is for things that change frequently. These seperated layers are for interacting outside of app that should not deal with domain problems. 

 

But what are the cons of Onion Architecture?

You may have guessed, learning curve and complexity. For small projects it may not be worth the effort to separate layers, introduce new interfaces, changing codebase etc. Developers with not so much knowledge about design patterns may struggle to implement it so they may require a preliminary study to implement it. As Palermo says "This architecture is not appropriate for small websites.  It is appropriate for long-lived business applications as well as applications with complex behavior".


Project Example with Code

For practicing and learning reasons i created a shopping cart web api project. Here i will explain how this architecture applied to this project.

 


 

I needed two entities: Product and Cart. This entities coupled to only itself and does nothing than representing objects. Note: This may not be best practice, here is a quote from Domain Driven Design book by Eric Evans:

Application Layer [his name for Service Layer]: Defines the jobs the software is supposed to do and directs the expressive domain objects to work out problems. The tasks this layer is responsible for are meaningful to the business or necessary for interaction with the application layers of other systems. This layer is kept thin. It does not contain business rules or knowledge, but only coordinates tasks and delegates work to collaborations of domain objects in the next layer down. It does not have state reflecting the business situation, but it can have state that reflects the progress of a task for the user or the program.

Domain Layer (or Model Layer): Responsible for representing concepts of the business, information about the business situation, and business rules. State that reflects the business situation is controlled and used here, even though the technical details of storing it are delegated to the infrastructure. This layer is the heart of business software.

Now, the more common mistake is to give up too easily on fitting the behavior into an appropriate object, gradually slipping toward procedural programming.

In domain service layer, i created CartService and ProductService interfaces to represent what domain logic needs.

I also created 2 custom exceptions for when product not found and cart not found. They are also located inside Domain Services.

In the application services layer i implemented my interfaces like adding products to cart etc. They are coupled to domain repositories not jparepositories!

For UI layer i created package called presentation.rest and implemented Rest Controllers here for requests like POST AddToCart.

Infrastructure layer used for Repository interfaces that extends JpaRepository, no boilerplate code.

 

You can find this code on my GitHub Repo: https://github.com/cankurttekin/market


Resources:

https://jeffreypalermo.com/tag/onion-architecture/

https://www.martinfowler.com/bliki/AnemicDomainModel.html

Domain-Driven Design: Tackling Complexity in the Heart of Software By Eric |Evans