Clean Architecture and The Art of Cooking Flavourful Code

Charles Prado
Geek Culture
Published in
8 min readJan 27, 2021

Writing good software sometimes can be hard, but maintaining it, it’s even harder.

Have you ever started a project with a simple idea at the beginning, but as it starting getting bigger and bigger you end up with a chaotic and very confuse repository, even for you who wrote it?

I think we’ve all been there at least one time in our careers. That is one of the main reasons we learn about project structures and best practices to make code cleaner. By abstracting our code, it becomes more readable and easier to maintain.

Think about Object-Oriented Programming Paradigm for example. There was a time when programmers wrote their code in a 100% procedural form. If you wanted to explain your code to someone else it was certainly a hard task. But with the introduction of OOP paradigm things became a lot easier, programmers now had a way to describe their code using examples of things that exists in real life. By creating a way to model our code using examples that are more related to our daily life, our projects become more easy to iterate.

With that in mind, I decided to write this article where I’m going to use a very high level / ludic sample, to describe what I consider the optimal way how projects can be written so we can end up with a clean and solid base that is: easier to understand, maintain and explain.

Said so, a project is a project, — be it coding or a business one -, so instead of simply creating a code project here let’s describe our structure by creating something else: a restaurant.

The restaurant case

Imagine you’re about to start a new restaurant business. First, you need to decide what type of restaurant it will be: it will be an Italian Food Restaurant, a Japanese, etc? Next, you need to define how your restaurant will operate, who will be your suppliers, your workers, how they should execute their tasks, and so on. The first thing to do here before starting our business certainly is defining the structure of it.

Be a software project or a personal business a universal truth is: “there are no silver bullets”, in other words, we’ll never find an optimal solution to all of our problems. But, even though a magic solution simply doesn’t exist, there are, however, already proven approaches to build a good project structure. One of my favorites is Clean Architecture, created by Uncle Bob.

NOTE: through out this article I’m going to use Swift language to provide some code examples. However, everything that will be described here is applicable to any other language of your preference.

Clean architecture

Image from Martin Fowler’s site

The image above is a very simple way to describe the base of the Clean Architecture. Although there are several variations of how to implement it, the core is always the same: we are going to separate our system into 3 layers: Domain, Data, and Presentation (you can read more about PresentationDomainDataLayering here). The Presentation only talks to Domain and the Domain describes what Data should do. With this simple concept in mind we now already have a well-defined structure that we can use to develop our entire project.

Now, let’s think about the analogy with the restaurant we’re doing here. If we are going to start our restaurant using the Clean Architecture, the Domain Layer would be our management area, the place where we, as the restaurant owner, will describe WHAT our restaurant will do, i.e the business logic. What type of food our restaurant will serve, which ingredients we going to use (our Models in code-world). Also, what our workers must do when they receive an order from the dining hall, from where should they get stuff from and so on.

As restaurant managers however, we don’t want be the one who’s cooking, taking clients’ requests, or wash the dishes. So we’re going to hire someone to do that. The Domain is the module that describes what our business does, while the Data Layer is where it will be described HOW that will be done.

Finally, to interact with our client, present him his table, and taking note of his orders, we will have the Presentation Layer: the dining hall.

If we convert those ideas to a code project, the structure you’ll have will look like this (being the CleanArchitectureRestaurant our Application and Domain, Data and Presentation frameworks):

NOTE: If you’re using this concepts to build an iOS project I highly recommend that you create the project modules using frameworks with different.project files. If you want to know more about the benefits of doing so I suggest you this great article written by Leandro Pérez

Serving a dish

To better illustrate the structure we just talked about, let's code the most basic task a restaurant execute: serving a dish. In this example, I’m going to describe how our restaurant will prepare and serve one of my favorite dishes: Spaghetti Carbonara.

Let’s now specify the role of each module we just talked, so we can accomplish the task mentioned in a very clean way.

The Domain Layer

As said before, the Domain Layer is where you’ll going to specify what your restaurant is, what will be executed in every part of our business — the business logic — but not how it going to be executed. Uncle Bob describes the Domain layer as “the blueprint of a project”, this is the place where someone can look and easily understand what is the business all about. If someone just looks at our Domain layer, it would scream: Restaurant (that’s what Uncle Bob calls screaming architecture).

Domain Layer must be the most framework agnostic as possible. You should not include any framework dependencies here. Remember: Domain describes “whats” not “how”.

So in our Domain, we will have essentially: (1) UseCases; (2) Models; (3) Protocols used by our UseCases and Models. In our case let’s start by defining the Model of a Carbonara and also the Protocols needed so we can pass this information to a Cooker later on:

Then, we need to specify what the kitchen should do when a Carbonara is requested at the dinning hall, i.e. the kitchen use case:

After defining what will our kitchen do, now we need someone that knows how to make these things work. In our KitchenUseCase we specified that we need someone that knows how to get stuff from our local store — a localDataSource — someone that knows how to get stuff from outside — a remoteDataSource — and finally, someone that knows how to cook the menus — a cooker . Those will be defined in our Data Layer.

The Data Layer

Now we define how we expect our workers to do their jobs, i.e. how they’re going to implement the UseCases described in Domain.

Let’s start with the Repositories implementation — our cooker assistants who will gather the ingredients needed by the kitchen:

The next step is to define one of our Cookers:

Being our Cooker defined in Domain layer as a CookerProtocol give us freedom to implement different Cookers types on our Data layer depending on what we need. We can have some ItalianCooker, some BrazilianCooker, JapaneseCooker and so on. That’s called Dependency Inversion Principle one of the five SOLID principles used in Clean Architecture.

I’ll not specify the NetworkManager nor the StorageManagers like CoreDataStorage, UserDefaultsStorage, etc here, but just keep in mind one thing: all those classes must only be accessed inside the Data Layer, your Presentation layer should never have the access to directly access or modify something from these entities. Remember: your Presentation Layer only talks with your Domain Layer, the Data Layer implementations must all be hidden from the rest of the application. Another way to put this is: “your customer should never ask for his food directly to the people working in the kitchen, (objects from the data layer), instead he should only request things for a waiter (ViewModel), or someone else working on the dining hall (Coordinators, Helpers, etc).

The Presentation Layer

Finally, at our Presentation Layer, or better saying, in our restaurant dining hall, the only information needed are those related to what our customer may need to make his requests, have his dinner and a great experience at our restaurant:

  • The table he’s going to sit (a View / ViewController)
  • Someone to conduct him to his table (Coordinators and/or Routers)
  • A waiter will be the bridge between the dining hall and the kitchen (ViewModel).

I’ll not go any further here describing how the code in PresentationLayer should like because that’s not the purpose of this text. You can prefer using InterfaceBuilder, programmatic view, SwiftUI, and so on, also, you can opt to use MVC, MVVM, MVP, etc. The only thing to keep in mind here is: Your Presentation Layer should be concerned only about things related to Presentation.

You should never do things like:

  • Requesting or setting data from the Network or Persistence layer in PresentationLayer.
  • Implementing business logic or specific operations not related to the project presentation.

Dependency Injection Containers

One last thing to consider before we finish. In the beginning, we talked that the Presentation Layer only talks with the Domain Layer. But to make things work we need to instantiate objects from the Data Layer. The way to do that is by using Dependency Injection containers — objects from our application layer that will inject data from one layer into another.

Inside our application module (CleanArchitectureRestaurant) we will import all modules we created: Domain, Data, and Presentation. Next, we create our DIContainers, and instantiate and inject everything we need to make our modules work as expected:

Conclusion

Now that all of our processes were defined we have our restaurant ready to open the doors and serve an amazing experience both for our users/clients and to whom is working with us.

By having our project structure well defined in our minds with a simple analogy of a real business we now have a very powerful tool to understand all our systems and also to make them more solid whenever we plan to start adding new features on it. We can know to replace questions like “should I place this code in here?” by “should my waiter be inside the kitchen cooking this dish?”.

Hope that helps you to write some cleaner code ;)

If you have any questions or suggestions for this text, feel free to contact me through the comments sessions below or via Twitter.

A huge thanks to GuilhE who help me a lot reviewing this article.

--

--