I found the perfect Architecture for Flutter apps.
As professional engineers, we all want to write maintainable and easy-to-understand code. But how can we succeed if we build on the wrong foundation? That’s where good architecture comes into play.
Each architecture serves its needs. So if you have a simple CRUD application, that will be an overhead for you. But in case you seek an enterprise solution, take a seat and read this article.
Part 1. Introduction. You are here.
Part 3. Fetching data. Coming soon…
Part 4. Conclusion. Coming soon…
As a reference, I’ve taken Hexagonal Architecture by Tom Hombergs. I really advise you to read his book. There are a lot of hidden depths.
Overview
Entity
- Domain rules
- Has no dependency on outwards components
- Pure Dart classes
UseCase
The software in this layer contains application specific business rules. It encapsulates and implements all of the use cases of the system. These use cases orchestrate the flow of data to and from the entities, and direct those entities to use their enterprise wide business rules to achieve the goals of the use case.
Input and Output ports
- Interfaces
- Every communication to and from the outside happens through dedicated “ports”.
- Input port: i.e. (UseCase)
- Output port: e.g. (Port)
Why do we need to slice persistence adapter instead of creating a general one? As Robert C. Martin said:
“Depending on something that carries baggage that you don’t need can cause you troubles that you didn’t expect.”
The Interface Segregation Principle provides an answer to this problem. It states that broad interfaces should be split into specific ones so that clients only know the methods they need. So when we work on some Service we just plug in the ports we need.
Adapters
- Form of an outer layer of the hexagonal architecture
- Not part of the core but interact with it
- Input adapters: Call the input ports to get something done. (Flutter UI/BLoC)
- Output adapters: Called by UseCase. Implementation of the output ports (e.g. Data Repositories, Cloud Repositories)
Input adapter
Output adapter
Organizing code
I think that organizing the packages has the same importance as writing clean code and making clean architecture. In my perfect world packaging structure represent and express your architecture. Just one look at the packages should say to you what architecture you are using.
My favorite is to create layer-driven packages (i.e. domain, inner, outer) with features-related code inside.
Thank you for reading till the end. I have a Telegram channel with useful articles that I try to post every day. Take care. See you in the next one.
Glory to Ukraine 🇺🇦