Flutter is a rapidly developing cross-platform framework. It is really perspective technology, the state of the art of cross-platform tech. So, let's figure out how to build a good supportable architecture of Flutter application.
This is the first part of a two-part article dedicated to flutter clean architecture. Today I would like to tell you CA theory. This knowledge will help you to deeply understand the second part, where you will implement a CA example.
Clean architecture is the concept by Robert Martin whose main idea is to separate architecture into loosely coupled layers. Thereby we have a good supportable, readable, and testable project.
Usually 3 layers are defined:
- Data Layer: Includes logic of communication with the - database, network apis, etc.
- Domain Layer: business logic layer.
- Presentation Layer: UI.
includes Repositories and Data Sources. Data sources implement logic of data access from different sources (such as network, database, disk etc). Repositories contain queries and mutations for a specific data model and can decide from which data source gets data (request it from network or get from cache for example).
contains Models and Use Cases. Models declare data format. Use cases combine data from one or multiple repositories. The Use case is a class where you extract the business logic out of your Presenter/ViewModel. This makes the Presenter/ViewModel simpler because it only coordinates the view and calls Use case. This approach helps to write testable, supportable code.
contains Views and Presenters / ViewModels (sometimes routers. It depends on the presentation layer architecture you choose). View is what users interact with and coordinated by Presenter / ViewModel which executes one or more Use Cases.
The Presentation Layer always depends on the Domain Layer. Data and Domain can depend on each other and it depends on the variant of implementation.
There are two variants of implementation - Data Flow and Dependency Rule. The main difference between them -
data flow’s domain layer depends on data layer while dependency rule’s data layer depends on domain. I prefer Dependency Rule and have a couple of reasons for it.
The first reason is that it works with Event Storming and DDD (Domain Driven Design) principles. I mean it is easier to design software driving by domain. Because domain defines business processes and is the most important part of the software.
The second reason is that flutter is cross-platform technology and it is very important to keep the freedom to use different storages (not only presentations) for different platforms (such as mobile and frontend and desktop in the near future). It is important for any long-term projects, not only cross-platform. But for cross-platform, it is required.
If we designed everything correctly, Domain doesn’t have any dependency on any other layer. Also, a good practice is not to use any external dependencies and frameworks. Try to use clean Dart.
To keep the domain independent from data, there is some approach for that. Domain Layer includes protocols of repositories, so data layer only implements it. And we just inject it by DI.
That's it. I hope you like this article. If this part looks difficult, don’t worry, you will understand these conceptions when you see how it to realize. In the second part, we will implement everything you have just read. See you there.