I found the perfect Architecture for Flutter apps.

Nikita Lapin
3 min readMay 27, 2022

--

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.

Photo by Danist Soh on Unsplash

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 2. Authentication.

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

Architecture overview (Main modules)

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.

Use Case implementation

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)
Input Port. Send Money Use Case
Output Ports. Load and Update Account 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

Input Adapter. Send Money BLoC

Output adapter

Output adapter. Data 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 🇺🇦

--

--