Introduction to Clean Architecture

Following a specific architecture when you're on a project is expected in software development. Clean Architecture describes one of the most important values about software: being easy to understand.

Following a specific architecture when you're on a project is expected in software development.

Architecture, in this sense, is considered the blueprint of a system. However, Mark Richards's book Fundamentals of Software Architecture provides a more detailed definition.

In this definition, software architecture consists of the structure of the system (...), combined with architecture characteristics (“-ilities”) the system must support, architecture decisions, and finally design principles [1].

This definition might sound intimidating at first, but I want you to remember that it is more than the structure of a system. It aggregates the many parts of the software.

What is the Clean Architecture

The concept of Clean Architecture was first introduced in 2017 by Robert C. Martin in his book Clean Architecture.

At the time, he admitted that this concept was not new and that it was part of different architectures, such as Hexagonal Architecture, BCE (Boundary Control and Entity) Architecture, and DCI (Data, Context, and Interaction) Architecture.

As the author puts it, all of these architectures have the same goal: separation of concerns [2], which is what Clean Architecture is all about.

Why is it Named Clean?

Leonardo Giordan in Clean Architectures in Python has a great definition of why it's called Clean.

(clean) describes one of the fundamental aspects of both the software structure and the development approach of this architecture. It is clean, that is, it is easy to understand what happens [3].
The clean architecture is the opposite of spaghetti code, where everything is interlaced and there are no single elements that can be easily detached from the rest and replaced without the whole [3].

The best definition to remember is that clean architecture should be easy to understand, with uncoupled and easily replaceable elements.

Clean Architecture

Now that we have defined this architecture, we can explore its principles, components, and complementary techniques.

Principles

This architecture relies on the separation of concerns. Every component should be independent and easily replaceable.

Here's a detailed list of all the principles in the book Clean Architecture [2]:

  1. Your architecture should not depend on the existence of external libraries or frameworks. They should be seen as tools instead and not limit your whole system into their constraints.
  2. It should be easily testable, this means that you should test your business rules without UI, database, web server or other external elements.
  3. If you need to use a database, it should be easily swapped out. Imagine that you're currently using Realm, it should be easily swapped with CoreData for example.
  4. The UI should be easily changed without changing the entire system. If you're currently using console as the UI it should be easily replaceable to web UI.
  5. Your business rules don't know anything from the other components and how they interact.

Layers

Even though you can get a brief idea of how this architecture works it's important to also talk about what each layer does.

Previously we talked about business rules, so let's start there.

A business rule is something that defines your system. For example, if you have an app that deals with selling online goods, a business rule could be having discounts for your customers.

Where can you place this? In the innermost layer of the application, the Entities.

Entities

As stated before, this layer is responsible for encapsulating your core business rules. This can be represented as objects with methods or sets of data structures [2].

They should be used by many different applications in the enterprise. This means that they do not depend on the platform, they are the same if you're using the system in the web, an iOS app or on a game console.

They are in the innermost layer because they are the least likely to change overtime [2].

If the business rule of applying discounts is removed can you say that the system remains the same? If it's a business rule it may be not.

Use Cases

The next layer is the application specific business rules. The use cases are responsible for orchestrating the flow of data to and from entities.

In this case we can have a use case of applying discounts for high-paying customers. You can easily detect that there are several domain specific elements in this. The use case will orchestrate how it can use the discounts and customers to deliver this.

Interface Adapters

This layer is the connector between the previous specified layers and the "outside". It will convert data from web for example to the data most convenient to the Use Case and Entities [2].

Can you use Clean Architecture if you don't have explicit interface adapters?

Many elements can be this layer without being explicitly named Interface Adapter, for example, if you're using MVC (Model, View, Controller) any presenter or controller can do this job of converting the data between the layers [2].

Frameworks and Drives

Finally, the last layer is the outermost layer and it usually has all of the external dependencies.

By doing this you don't need to worry if a certain framework is outdated, it can easily be interchanged due to how the architecture is constructed. You're creating a sustainable system that will require less maintenance over time.

In this layer you can have everything that is specific to the platform or tools that you're using for your system. For example, if you're using a database, Core Data should be in this layer.

But what does cross the boundaries between each layer?

Isolated simple data structures that can be passed through function calls (completions for example). You cannot however pass entity objects or database rows [2]. If so you're leaking logic from one layer to another.

But how can all the layers interact without crossing boundaries with one another?

To put it simply you the layers won't cross boundaries if you use the Dependency Inversion Principle.

Dependency Inversion Principle

This might sound intimidating but I'm certain you used this before.

This means that to communicate between layers you refer to abstractions and not concrete classes [4].

Representation

After explaining all of the layers we can move on to the graphical representation of this architecture.

You might be familiar with the representation made by the author of the book I referenced. But let's take a step further and add all of the different elements of the example that we talked about before.

Conclusion

Clean Architecture was created from a mix of other similar architectures with similar objectives: keep different concerns separated. This will create a system that is easily testable, changeable and maintainable. By doing this it simplifies the life of engineers that work on that system in the future.

However, it's important to note that not everything is perfect. This architecture may be very intimidating when you're first starting out. There are a lot of layers to create if you're just doing a simple application. Even though it seems like an overkill it's important to keep in mind that when your application grows it will become more and more complex and if you're not adopting this architecture right away it will be harder to scale.

I hope you enjoyed this article, I'm a very big fan of clean architecture and wanted to showcase what it entails and how each layer interacts.

If you enjoyed this please consider supporting my work by connecting with me on LinkedIn, GitHub and X.

Do you have a suggestion for a next topic? Let me know through e-mail on: vera at codingwithvera dot com ✨

References

[1] Designing Software Architecture, Introduction, Fundamentals of Software Architecture by Mark Richards, page 17

[2] Chapter 22: Clean Architecture, Clean Architecture: A Craftsman's Guide to Software Structure and Design by Robert C. Martin page 177 to 184

[3] Introduction: Clean Architecture in Python by Leonardo Giordan page 3

[4] Chapter 11: The Dependency Inversion Principle: Clean Architecture: A Craftsman's Guide to Software Structure and Design by Robert C. Martin page 84