Desgining APIs with Clean Architecture

REST API development using FastAPI Framework (Python) while managing dependencies using Clean Architecture

Clean Utensils in a Bicket
Image Source: https://www.diybeautify.com/2020/03/easiest-way-to-clean-stainless-steel-utensils-cutlery.html

“If all you have is a hammer, everything looks like a nail.” — Abraham Kaplan

What the heck is a Clean Architecture?

At the heart of Clean Architecture and similar styles such as Hexagonal Architecture is the ability to test and develop the business application independently of the rest of the infrastructure. Therefore, in Clean Architecture, the business rules form the actual core of the application and thus define its value. Especially in complex software projects, further development is never complete. Clean Architecture has the effect of preventing individual software solutions from influencing the overall process and thus burdening and hindering business processes. Likewise, components of the infrastructure can be defined at a later stage or also exchanged or replaced, which represents a further advantage of the Clean Architecture in comparison to traditional Three Tier Architectures.

Three Tier Architecture

Three Tier Architecture is one of the most if not the most prelevant way of designing a system. It comprises of three different part of the system:

  1. Data Tier — Responsible for handling all the Persitance in the Data.
  2. Business Tier — Responsible for all the business logic and flow of controls.
  3. Presentation Tier — Responsible for representation of those data in expected form of information.
Image Source: https://www.finereport.com/en/product-functions/3-tier-architecture.html

Albeit being easily understandable and widely used, Three Tier Architecture faces a vital flaw due to it’s one directional data-flow mechanism. And that is the business layer in this is heavily influenced by the data layer, which is probably bound the infrastructure choices. Any change to data model would propagate to business layer and so forth, causing constant need for refactoring and restructuring of logic.

Clean Architecture

Clean Architecture, as opposed to Three Tier Architecture, does not define it’s layers in form of Tiers or Steps, but instead as a Ring of dependencies. In this, the outermost ring is more susceptable to a environment change while innermost is almost immune from it.

Image Source: https://www.techtarget.com/whatis/definition/clean-architecture

As it can be seen, being at the innermost level, the Domain layer is quite independent of how the Data Models are being loaded and persisted into the system, as long as they are accessible. Each individual infrastructure and other outside influence is being designed as Adapter and attached to the Port exposed by inner layer for it to consume.

Designing an API

An API (REST and others) have to basic components attached to it- Schema and a data store. We can think of the schema as our presentation layer and susceptible to change based on Consumer application and API Client requirements. But this might not always require changes in our business logic or even entity models. Similarily, any new change in internal algorithm does not require any modification in either schema or entity. Any upgradation of Database system only should affect entity defintions at most. Ok, now that we set ground rules for our application, let’s architect the solution.

Problem

In this example application, we have two Domain Model — Author and Book. An author can write one or more books, and similarily one or more authors can write a book. In a nutshell, these models enjoy a Many-to-Many relationship between them.

Model Schema

Let us define our Models, one after the other along with the Association.

Repository

To encapsulate all the Database transaction, we create a layer called Repository composed of Entity Models. Both Entity and Repository corresponds to Enterprise Business Logic and a part of the Domain itself.

Services

Once the groundwork for our data resource has been done, let us focus on you business needs, which will handled by the Service Layer. A Service is a set of rules that dictates behaviour of an application and it is a way providing Context to above said Domain.

A quick set of requirements of the application would be-

  1. As a consumer of these APIs, I would like to see the list of Authors.
  2. As a consumer of these APIs, I would like to see the information about a particular Author.
  3. As a consumer of these APIs, I would like to add to the list of Authors.
  4. As a consumer of these APIs, I would like to edit the information about a particular Author.
  5. As a consumer of these APIs, I would like to delete the information about a particular Author.
  6. As a consumer of these APIs, I would like to see the list of Books.
  7. As a consumer of these APIs, I would like to see the information about a particular Book.
  8. As a consumer of these APIs, I would like to add to the list of Books.
  9. As a consumer of these APIs, I would like to edit the information about a particular Book.
  10. As a consumer of these APIs, I would like to delete the information about a particular Book.
  11. As a consumer of these APIs, I would like to see the list of Books written by a particular Author.
  12. As a consumer of these APIs, I would like to see the list of Authors for a particular Book.
  13. As a consumer of these APIs, I would like to add to the list of Authors for a particular Book.
  14. As a consumer of these APIs, I would like to delete from the list of Authors for a particular Book.

And to implement these, we create two services:

Router

Now that all pieces are in place, final shot has to be building the Interface Layer, a.k.a. API endpoints.

Conclusion

Clean Architecture let’s you decouple the system into multiple independent block of resource capable of doing a unit of work themselves. This makes the system robust, easy to change, less prone to error and even easy to test standalone. There are already few tests present in the repository to showcase how independent part of the system can be tested standalone, more coming in following days.

Update

I have taken time out and implemented the same for multiple other language and framework for people to relate easily.

NestJS: https://github.com/0xTheProDev/nestjs-clean-example

Spring Boot:https://github.com/0xTheProDev/spring-clean-example

Ruby on Rails: https://github.com/0xTheProDev/rails-clean-example

--

--

Progyan 👨🏻‍💻 | #TheProDev

Software Engineer turned Architect | Upcoming Data Engineer | Start-up Advisor | Open Source | Philanthropist