Clean Architecture

Michael Bui
NE Digital
Published in
6 min readMar 26, 2021

The common mistake

As a Team Lead in NE Digital, one of my responsibilities is hiring new developers for the team, and interviewing is the most time-consuming but the most interesting step of the hiring process because it helps me to understand much more about the developer.

In the interview sessions, I usually don’t ask much about the details that we can easily (or sometimes difficult) find on the Internet like:

  • What are sorting algorithms and their complexity?
  • What is the fastest algorithm for graph traversal?

Instead, I usually ask about the experiences & the mindset of the developer and one of my favorite questions is:

  • If I want to build simple a Todo app, what are the steps you will do?

Surprisingly, from all of the candidates, one of the first steps is design DB structure (⚠️).

Does it sound familiar to you? If you do feel so, this article is definitely for you!

Our brain is behaving so differently

Imagine on your birthday, you’re brought by your best friend to a new restaurant. What can be the first question you will ask about the new restaurant?

Let me guess:

  • What’s the name of the restaurant?
  • What are the dishes?
  • What’s the best dish?

If I’m guessing right, can you see how interestingly your brain behaves differently in this situation? Why don’t you ask: how are the food and ingredients stored? ?

You may argue that my example is from the audience’s point of view, not from the author’s point of view. But really, if you are building a restaurant, will food & ingredients storage be one of your most concerns? Then why should data storage (or DB) be one of our first concerns?

The “Clean Architecture”

Oh well, if data storage should not be one of our first concerns, then when should we raise a concern about it? If you’re thinking about the last concerns, you are surprisingly correct!

Yes, that’s true! Like how you are planning to build a restaurant, food storage should be one of your last concerns. Instead, you should first think of the menu, the recipe, then the food and ingredients. You really need to make sure these things are good, verified, and totally meet your expectations first. After that, you can start thinking about food storage, dish decoration, restaurant organization,… and you’ll have to make sure these things are flexible and can be amended quickly to adapt to seasonal demands or market changes.

Similarly, in software development, you should first think of the features, the logic, then the core business entities. After that, you can think about data storage, data presentation,… in your architecture. And if that architecture allows those things to change quickly, your architecture is considered a “Clean Architecture”.

A “Clean Architecture” is a software architecture that first focuses on the business entities, the related logics (or use cases) to make sure they are flexible, quickly adapted to business requirement changes, then defer the decision for data storage, data representation, UI,… to the last steps.

From theory…

Ref: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

The basic idea of Clean Architecture is quite simple: you should architect your system in layers that:

  1. The most important and static layer is at the most inner layer
  2. The external systems (DB, UIs,…) are at the most outer layer.
  3. Between them can have one or multiple layers but they must depend on abstraction via interfaces, not on details
  4. The code dependency direction should always point inward from the outer layer to the inner layer.
    In practice, I’ve just found only one exception that is for data access flow, where the code dependency direction is pointing outward as I will show later

To practical

In NE Digital, we build the systems following microservice architecture, and we keep the architecture of each service simplest (as seen in the below diagram) to make sure the architecture is flexible enough while minimizing development time & effort.

We divide our architecture of each service into only 4 layers:

  1. The most important layer, also the core of the service is Model (in yellow). This is where all of the business entities are defined
  2. The second important layer isService (in blue) where all of our business logic reside in.
  3. The third layer is the boundary where all the connections between the service and the external systems are done. This includes but not limited to:
    * Handler : is the place where all API requests are handled, converted into Service‘s compatible params to process
    * Job : is the place where all job (mostly Cronjob) inputs gathered then are converted to Service ‘s compatible params to process
    * Subscriber : is the place where all PubSub messages are captured, converted into Service‘s compatible params to process
    * DAO: is the place where all data operations (e.g: CRUD) are done with external data systems which include not only Database, Cache but also API, Message Queue,…
  4. Sometimes the microservice is a bit more complex, we will have the 4th layer which is the internal helper layer (in green) that our Service layer needs to fulfill the business logic. It includes Parser , Validator , Renderrer ,…

Example

As a Team Leader, I need to measure some metrics of my team’s performance. We are using JIRA in NE Digital but since JIRA doesn’t have those metrics built-in, I have to write a job to consume its APIs to collect data and build metrics by myself. This is how I architecture the job:

And here is how the code structure looks like:

You can see that I divide the code base into 4 layers that match what I mentioned above:

  1. Business entities: model
  2. Business logics: service
  3. Boundary: job , dao
  4. Internal helpers: parser

By doing this, I want to free ourselves from making decisions for frameworks. Currently job is using corba framework to construct the input data and pass it into service . Later if we want to change the framework, we can just make amendments in job . Moreover, if we want to invoke this process not only via Cronjob but also via API (or even Message Queue), we just need to create handler (or subscriber ), construct the related information into service compatible input data. Nothing else needs to be done!

By architecting our system like this, I also want to free ourselves from making decisions for data storage:

Currently, we have API & MySQL but we are free to add any other data storage systems like Redis, Mongo or BigQuery,…

We can even make that decision only per entity without any impact on other parts of the system.

Summary

I have been a passionate software developer for more than 10 years, I have made almost every mistake that a software developer can make. And I have to admit that the biggest mistake I’ve made was thinking that my primary responsibility as a software developer is writing functional code for requested features.

The truth is that writing functional code is just our secondary responsibility, and:

The primary responsibility of software developers is writing code that can be quickly adapted to the changes of the market, or the changes of business requirements.

This article about “Clean Architecture” is just a small part of the primary responsibility but I hope it will move you and our developer community a step closer.

What’s next?

These are the recommendations from bottom of my heart:

--

--

Michael Bui
NE Digital

Product Development Lead • A modern leader in IT, obsessed about impactful products & successful businesses!