Mastering Flutter: Building Scalable and Maintainable Apps with Modular Architecture [en]

Salih Can
5 min readJul 1, 2023

--

Greetings to everyone,

Modular architecture mobile applications provide many advantages such as flexibility, sustainability, and reusability in the development process. Those advantages are particularly important, especially when developing large-scale applications with high scalability. Flutter is a popular framework that provides a powerful solution in this field.

In this article, we will explore how we can develop a multi-modular application using the Flutter framework. The multi-modular architecture allows the application to be divided into independent modules, enabling each module to fulfill its own responsibilities and functions.

Each module represents a specific property or function and can be developed, tested, and delivered independently.

Approach Architecture

The importance of choosing the right architectural approach for developing a modern mobile application lies in providing sustainability, scalability, and ease of maintenance. In this context, using a modular architecture provides a significant advantage.

In this section, we will discuss the advantages of the modular architecture approach used in Flutter, the layered structure, and the relationships between these layers. Additionally, we will explain how to manage modules and module dependencies, as well as discuss the overall structural characteristics of the application.

Advantages of Modular Architecture

Modular architecture allows for the division and independence of a Flutter application into separate parts. Each module focuses on its own responsibility area and helps to alleviate the complexity of the overall application structure

These approaches include the following advantages:

  • Higher Sustainability: Modular architecture allows for the isolation of different parts of the application. Each module has its own responsibilities and boundaries, which makes the codebase more sustainable and easier to maintain.
  • Scalability: The use of modular architecture enables easier scalability of the application when adding new features or extending existing ones. Adding new modules or updating current modules can be done without affecting the overall structure of the application.
  • Dependency Management: Modular architecture makes the management of dependencies easier. The dependencies between modules are clearly defined, preventing dependency conflicts and complexities.
  • Parallel Development: Modular architecture makes it easier to work in parallel with a team. Each module can be developed by a different team member, and changes made to one module do not affect other modules

Application Layers and Relationships

Recipe Finder — Moduler Architecture

A modular Flutter application generally consists of four main layers: Domain, Data, Presentation, and Core.

In the visual above, you can see the modularized version of the ‘Recipe Finder’ application, which has been completed at the end of this article series.

  • Domain Layer: This layer encompasses the fundamental business logic and processes of the application. Data models, services, operations, and other domain-specific classes reside in this layer. The domain layer represents the core functionality of the application and is independent of other layers.
  • Data Layer: The Data layer is responsible for processing and managing application data. It provides access to data sources such as APIs, databases, etc., performs data transformations, and performs data storage operations if necessary. This layer abstracts the domain layer’s access to data.
  • Presentation Layer: The Presentation layer is the layer where the user interface is created and user interactions are performed. It includes widgets, screens, forms, and other components focused on the user interface. This layer interacts with other layers to display the user interface and handle user actions.
  • Core Layer: The Core layer is independent of any other layer in the project and, conversely, other layers depend on this layer as a source of nourishment. This layer contains features that can contribute to the project as a whole, such as base structures and general extensions.

The relationship between these layers is established through a one-way flow. The Presentation layer depends on the Domain layer and utilizes the business logic. The Data layer, on the other hand, receives data from the Domain layer and provides access to data sources.

The Management of Modules and Dependencies

A modular Flutter application enables the independent development and management of each module. Modules are typically separated based on functionality or features. Each module can contain its own domain, data, and presentation layers.

The dependencies between modules are managed using dependency injection. Dependency injection allows dependencies to be passed between modules and enables each module to use its dependencies. This reduces tight coupling between modules and prevents changes in one module from affecting others.

For managing modules and dependencies, dependency injection packages are commonly used. Popular dependency injection solutions for Flutter include packages like “get_it”, “injectable”, and “kiwi”. These packages facilitate dependency injection and help solidify dependencies between modules.

The general structural features of the application depend on the design of the modular structure and the dependency injection solution used. A modular architecture increases the scalability, maintainability, and ease of maintenance of the application.

Example Application: Recipe Finder

Since we have been talking about modular applications, let’s reinforce what we have discussed by creating a sample application. You can find the source code of the sample application at the end of the article.

I have created the file structure for the sample project named ‘Recipe Finder’ as shown above. I have explained the presentation, domain, data, and core layers. I have created these layers under a folder named ‘modules’ with Flutter package examples.

In modular architecture, you may encounter two challenges. One is managing module versions and third-party dependencies, and the other is dependency injection.

  • I have solved the first challenge using a package called ‘melos’. With Melos, you can run different commands for each module or execute the flutter pub get command for all sub-modules with a single command.
  • I addressed the second challenge of dependency injection by using the ‘get_it’ package. Having worked as an Android developer for a long time, I have implemented dependency management using annotations, which we call tags. To continue this practice in Flutter, I decided to use the ‘get_it’ package empowered by the ‘injectable’ package. With these two powerful packages, I have successfully solved the problem of dependency injection.

As a result of these solutions, the project’s basic skeleton structure became as follows.

With this article, I have provided an introduction to the question of ‘how should modular architecture be?’ and introduced the basic skeleton of the sample project I created. The answers to questions such as how to perform dependency injection and how to use these packages can be found in the documentation pages of the respective packages. Both packages have extensive documentation.

Oluşturduğum örnek projeyi aşağıdaki bağlantıdan inceleyebilirsiniz.

You can review the sample project I created at the following link.

You can reach out to me here or through channels like LinkedIn if you have any questions. See you soon! 👋

--

--