Clean Architecture primer

The word "architecture" is overloaded in so many ways. Even in the software engineering domain, it doesn't mean the same thing for everyone. Either way, having some kind of guidelines/rules/architecture (however you want to call it) when building any kind of app (mobile, web, desktop) helps with constructing a sane and consistent codebase.

This is not a complete summary of Uncle Bob's "Clean Architecture" book. Rather I consider it a refresher for a specific part for anyone who has already read the book. If you haven't read it, please go ahead and read this as I consider it a primer for the most important part of the book, which is the Clean Architecture pattern itself. If it piques your interest, go and read the entire book :)

The main idea

Clean architecture, similar to Hexagonal Architecture, aims to create a codebase with the following characteristics:

  • Independent of any framework
  • Independent of any UI technology
  • Independent of any specific database
  • Testable

The reason for this "will for independence" is that any specific technology or framework can be considered a "detail". The most popular framework today doesn't mean it will last forever. When designing your software system, you should aim for it to outlive any (maybe) temporary trend in the software engineering industry.

Building something that is architectured with these characteristics, means that you can replace any deprecated technology with a newer one, without too much hustle. I say "without too much", and not "without" because replacing one UI framework with another is never trivial, no matter how well architectured is your app. But either way, having something well structured and not too coupled, makes these replacements doable instead of almost impossible.  

The layers

You may have seen the above diagram before but not fully understood what it means. These are the main layers the clean architecture suggests having. Let's deep dive a bit into them.

The dependency rule

Maybe the most important bit from the diagram. Source code dependencies should only be inwards, towards "higher-level" layers. The inner circles know nothing about the outer circles. This implies that any data classes/models that are created in an outer circle, should never cross boundaries to inner circles (e.g. any framework-specific classes).

Entities

The most inner circle, meaning the most high-level. These are the "enterprise-wide application-independent Critical Business Rules". If you are working in an enterprise with many applications, the Entities can be reused in all the applications ("enterprise-wide application-independent"). If not, the entities will be the business objects of the app.

Use Cases

These are the application-specific business rules. They coordinate the Entities and the Data Access Interfaces to actually perform some specific operations.

Interface adapters

Responsible for converting data between Use Cases & Entities to whatever the external dependencies (e.g. frameworks, DBs) understand.

This layer includes UI interface adapters which are any objects the UI architecture requires: presenters, views-models, and controllers.

Also, this layer includes the DB interface adapters. No matter how well-established a technology is (e.g. SQL) it should be abstracted in this layer (e.g. using repositories).

Frameworks and Drivers

The external dependencies, such as specific frameworks. The only code we need to write here is any glue code to communicate with inwards circles.

When to use

As usual in software engineering, this is not a "one solution fits all" architecture.

Ideally, projects which have the following characteristics will benefit the most from such an architecture:

  • Long-running multi-year projects
  • Multiple clients needed (e.g. web, mobile, desktop)
  • Multi-teams projects
  • Projects with complex domain logic
  • Volatile projects that requirements might change

For simpler projects, maybe with not so much business logic, this architecture might be an overkill. But this doesn't mean that we should not use anything from here. Just pick which layers best fit your specific case and implement only a subset of those. Finally, the main ideas of the architecture (independence from external dependencies)  should be followed as much as possible.

Hopefully, you got a glimpse of the Clean Architecture and if it looks promising there are countless resources out there to deep dive :)

Happy coding!