Do you remember the first time you wrote code? Maybe it was a hello world or some other first little program. It was great, seeing a couple of lines of code start to work... A couple of lines unless it was Java code.
If you are reading this, it may have been a long time since you wrote that little program. The world has changed, it's not like before. We have gotten into projects and experiences much more complex than our first contact with the world of software development.
Challenges arise from complexity.
I don't know if anyone said that but it sounded cool.
One of the biggest to come out has been scalability, which in short terms is defined as the ability of a system to grow in workload without dying while trying.
Also, when a project grows, it must be reliable, meaning that we can rest assured that it will not die or at least not easily. To ensure reliability, you have to maintain code with its tests passed. In a nutshell, your code must be properly tested to ensure it works.
Finally, there is a feature that many users do not perceive since they don't see the codebase, but this says a lot about any system that has it. This is called decoupling, which is closely related to code reuse and independence of each piece of software.
We decouple so that our code is modular and we can play with it as if they were LEGO pieces that we can change in size, shape, or color as long as it fits. This way we have reusable parts and we are more productive with organized code.
I could spend a lot of time talking about how we can write better code and good practices, but we better explain Clean.
Clean is an architecture suggested by Robert C. Martin, Uncle Bob for friends. It claims to meet all of the characteristics I mentioned previously and has a ... let's call it golden rule.
The Dependency Rule
To save me complex explanations, I am going to show you a graph. Don't over-analyze it, I just want you to think about the shapes that are presented:
Ignore the words and notice that they are only circles containing smaller ones. That's the graphical representation of the dependency rule, which if paraphrased would be something like:
Dependencies go from the outside in. That said, dependencies don't know anything about the components that depend on them.
Still don't understand? Let's use the words that are there.
The circle that contains everything we can see that has the UI, let's use it in the example. Our rule says the UI depends on the Controllers but a Controller doesn't know what's in the UI. So with the other circles and those that contain them.
Once again and in another way: The small circle is used in the large circle and NOT vice versa.
I hope you understood because from now on I am going to assume that you did. If not, there is more information on Uncle Bob's Clean Coder Blog.
⚠️ Given the most basic concepts of this huge topic, I want to clarify that I'm going to focus the following volumes of this series of articles on the development of apps in Flutter with Clean since that is what I do.
Specifically for Flutter, Clean has a slightly different implementation because of how the framework works in the integration of logic and the graphical interface. We can't decouple much in this case since they are too closely related, but we can extract in two layers:
- Domain: extracts the contracts in the system (interfaces, or abstract classes in Dart).
- Data: implements the contracts and obtains the data that the system uses.
Later we will delve into the components of these layers.
A common use-case
At this point, we have already explained quite a bit of the basics that are required to understand the following articles, but I wanted to make a few last observations and conclude.
Each of the layers or circles that Clean has can work independently of its outer dependencies or the circles that contain them.
I'll give you a practical example of why's that.
Let's say we are doing a project that initially has a REST API to interact with the backend and we make all the models of our application closely linked to the JSON format. Everyone lived together in harmony, but everything changed when we were asked to switch to an API with GraphQL.
Rings a bell? Yes, it happens to the best teams. And if we don't have a good architecture, we will probably have to make that migration from scratch.
The advantage of a good architecture is that our entities allow us to implement models with their own properties based on the technology they have to implement. So that our JSON models have the same properties as GraphQL and only vary in implementation.
Oops, we haven't talked about entities yet, sorry. If something I said didn't make sense to you and left you confused, then calm down, the following volumes are coming for you to understand better.
In the meantime, let's wrap up this article.
I tried to make a slightly more beginner-friendly version of the original Clean Architecture article on the Clean Coder Blog (I left the link before, but I leave it here again).
So as in that post, I will emphasize that implementing this clean architecture doesn't mean following the graph you saw before. If you search for more on the subject, you will find many more graphics that mention other aspects and that's the point, this changes depending on the project.
What you have to take into consideration is to really implement the architecture by always using the dependency rule. With that principle, we already follow the decoupling as it really should. The level of abstraction you want to implement in your code is up to you. As you become more abstract, even more layers can emerge.
I finish by saying that following this rule is very simple so I hope you do it and we will still have examples and more advice in the following articles (I have already said it a lot but it's for you to stay tuned) so that you do not suffer making and --more importantly-- maintaining good software.