Why use onion layering?

Abstract

Some good arguments on why using onion architecture:

  • reduce blast radius of change
  • accelerates understanding

Reviews

2024-07-13

It’s always advantageous to adopt architectures that promote low coupling. Examples include onion architecture, hexagonal architecture, clean architecture. These approaches emphasize the primacy of the domain layer while treating external adapters as secondary concerns.

However, it’s important to note that these architectures are not suitable for every situation. For instance, scripts and simpler applications may not benefit from such complexity.

You know you got it right if you cry more each time you look at another layer. That’s why it’s called onion architecture. - Top Reddit Comment

Context

For those seeking to understand what onion layering is and its relationship to other architectures I recommend checking out some of my favorite articles on the topic here 👉 what is onion layering?

This post provides a terse overview of why you might pursue onion layering with a few examples.

Rationale

1. Reduces blast radius of change

Code Base Damage There is a constant assault on our code base in the form of feature enhancements, bug fixes, and hygiene. Envision each incoming change as a bomb 💣, and the damage it does is based on the number of files impacted. Onion layering promises to reduce this blast radius.

2. Accelerates understanding

Reduces time to understand existing behaviors

Each change bomb is typically unique and requires a deep understanding of our code bases existing behaviors. Onion layering promises to reduce the time to understand existing behaviors.

Examples

Adding a field to our API

Imagine the most annoying possible client of our microservice. Suppose they want a new field, and they insist that it be named a certain way. Not only that but the API Stewards mandate that the new field be prefixed with a 25 character prefix and 45 character suffix.

The resulting request object that hits our system is horrifyingly ugly. It will sit in the .api.* layer of our onion architecture, and it will go no further. Our .core.* classes will not be beholden to the insane demands of our clients. Instead we can represent this new field in an idiomatic way that feels native to the language we are using.

Onion layering reduced how much pain our clients inflicted on our code base to the .api.* package and in doing so also increased the readability of our .core.* package.

Example damage control|800

Introducing a new downstream dependency

Imagine the most annoying possible microservice dependency. Suppose every input field is an acronym, they are using SOAP, and in the middle of revamping their whole API design.

The raw code to interact with this dependency is horrifyingly ugly and has inevitable upcoming changes. It will sit in the .infra.* layer of our onion architecture, and it will go no further. Our .core.* classes will not be beholden to speak the deprecated language of our downstream dependency. Instead we will reflect exactly what we need with the latest ubiquitous language of our team via an interface in .core.*.

Onion layering reduced how much pain our dependency inflicted on our code base to the .infra.* package and in doing so also increased the readability of our .core.* package.

Example damage control - dependency|800

Introducing a new library dependency

Imagine the most annoying possible library dependency. Suppose they have an interface we need to use, but constructing the object requires 10 configuration fields, 5 separate object dependencies, encryption algorithm selection, and a custom HTTP client.

The raw code to wire up this dependency is completely irrelevant to our existing behaviors. It will sit in the .config.* layer of our onion architecture, and it will go no further.

Onion layering isolates the distracting details of our new library into the .config.* package and in doing so also increases the readability of the rest of our code base.

Example clarity - configuration isolation|800

Appendix

Discussion Threads

Lucidchart Folder