avatarOlivier Revial

Summary

The provided content discusses the adoption of Clean Architecture in a new Flutter project, emphasizing its benefits in terms of simplicity, scalability, maintainability, and testability.

Abstract

The author begins by outlining the decision-making process for choosing an architectural pattern for a new project, considering factors such as ease of use, learning curve, scalability, maintainability, code quantity, testability, and stability. After evaluating various approaches, the team settled on Clean Architecture due to its alignment with their criteria. Clean Architecture, popularized by Robert C. Martin (Uncle Bob), is described as a pattern that incorporates and simplifies concepts from Hexagonal and Onion Architectures. It comprises four layers: Domain, Application, Infrastructure, and Presentation, with dependencies flowing inward to ensure the core business logic remains independent of external frameworks or technologies. The article then details how Clean Architecture is implemented in a real-world Flutter app, focusing on the three core layers: Presentation, Domain, and Data. The Domain layer is central, containing business logic, while the Application layer orchestrates data and business rules, and the Presentation and Data layers handle UI and external data sources, respectively. The article emphasizes the importance of dependency injection and the decoupling of components, particularly repositories, to maintain the purity of the Domain layer.

Opinions

  • The author believes that Clean Architecture is well-suited for serious company applications due to its focus on maintainability and scalability.
  • The article suggests that Clean Architecture's simplicity and ease of adding new features make it a preferable choice over other architectural patterns.
  • The author values the independence of the Domain layer from external dependencies, considering it crucial for the application's long-term usability.
  • There is an opinion that a well-defined architecture is essential for the success of a project, as it affects the app's ability to be easily tested and confidence in the codebase.
  • The article conveys that using Clean Architecture in Flutter helps in creating a structured codebase that can grow without becoming unwieldy.
  • The author endorses the use of dependency injection as a key component in implementing Clean Architecture effectively.

Multi-packages Clean Architecture in Flutter — Why

Photo by Brett Jordan on Unsplash

When I started a new project from scratch six months ago with my team, we took a few days to think how we wanted to code, how we wanted to architecture our app, etc.

Defining choice criteria

In terms of project architecture we could have gone in three different directions:

  1. not really caring about a specific architecture
  2. inventing our own code architecture
  3. using well-known architectural patterns

To make our decision we first started reading a lot of articles on architectures and tried to see which choice best fitted criteria we defined. Our criteria are the ones — we think — that make any serious company app actually usable in the long run:

  • Simplicity of use. Will it be easy to add a new feature to the app ?
  • Learning curve. Will it be easy for newcomers to understand the app ?
  • Scalability. Will the code still be usable as the app grows ?
  • Maintainability. Will it be easy to change an existing feature, to substitute a library for another ?
  • Quantity of code. How many files and lines of code will be required to add a new feature ?
  • Testability. Will the code be easy to test, will we have an overall confidence on delivered code ?
  • Stability. How likely will we have bugs and regressions, how easy is it to fix them ?

Understanding Clean Architecture

Clean Architecture is one of the possible architectural pattern for an application, and is pretty easy to comprehend. Popularized by Uncle Bob ten years ago, it is not a brand new pattern but instead tries to aggregate existing and popular patterns such as Hexagonal Architecture or Onion Architecture, maybe in a simpler way:

Clean Architecture diagram

At the center of this architecture we find the Domain layers that contain the most essential and business-specific logic of the application. It is isolated from external dependencies and frameworks, making it highly independent and reusable.

The next circle represents the Application layer, which orchestrates the flow of data and business rules between the Domain layer and the outer layers. It encapsulates application-specific logic.

Finally, the two outermost circles represent the Infrastructure and Presentation layers, which deal with external concerns like frameworks, databases, UI and external services. These layers also provide implementations of interfaces defined in the Domain and Application layers, enabling communication with external systems.

The arrows in the diagram depict the flow of dependencies, illustrating the rule that dependencies should always point inward, from the outer layers towards the inner layers. This ensures that the core business logic remains decoupled from specific frameworks or technologies, promoting maintainability, testability, and flexibility in the software system.

This architecture seems to fit pretty well our criteria mentioned above.

Clean Architecture in Flutter

We’ve seen the concepts behind the Clean Architecture pattern but you might still be wondering how this architecture translates in a real-world Flutter app.

From what I have seen so far, most Flutter implementations of the Clean Architecture use three layers as their core structure:

  • Presentation layer is responsible for the user interface and user interactions. It encompasses the UI components, such as screens, widgets, and controllers, that are responsible for rendering and receiving user input. It also contains the display logic so this is typically where your state management goes.
  • Domain Layer contains contains the core business logic and rules of the application. It represents the heart of the application and is independent of any external dependencies. It defines the entities, use cases, and business logic that drive the application’s behavior.
  • Data Layer is responsible for handling data persistence and external data sources. It includes components like repositories, data mappers, and network clients. The Data layer provides implementations of interfaces defined in the Domain layer and interacts with external data sources such as databases, APIs, or local storage. It is responsible for retrieving and storing data, as well as mapping data between the format used in the Domain layer and the format used by the external data sources.

Finally, note how the arrows dict the flow of our architecture: domain layer does not have any knowledge of the outer layers, including the UI or specific data sources. It is very important to understand this: domain layer should be pure from any other layer dependency as well as agnostic from any framework or specific implementation details.

Let’s now see zoom on our Clean Architecture structure by looking at this great diagram from Reso Coder’s Flutter Clean Architecture Proposal:

Reso Coder’s Flutter Clean Architecture Proposal

Note how the colored arrows are showing how the data is flowing from the infrastructure details (getting data from an API or a DB) up to the widgets that actually displays something with the data. Keep in mind that those arrows do not indicate the dependency flow, domain is still a pure set of classes that has no knowledge of presentation and data layers.

Notice how the repositories component has two colors: this is exactly how we will have a great decoupling! Repositories interfaces will be defined in the domain layer (e.g. “a method that gets a user”) whereas the implementation of this interface will be left to the data layer (e.g. “I will fetch a user from the backend API”). We will later use Dependency Injection to register the proper implementation for each interface.

🧐 What’s next ?

Ready to see how we split our app into multiple packages ? Go!

Flutter
Clean Architecture
Recommended from ReadMedium