Boosting Flutter Productivity Through Modularization

Muhammad Luthfi Arifin
7 min readApr 8, 2023

--

🚀 The process of dividing a large codebase into smaller, self-contained modules.

The messy and well-organized bookshelf. The left side is before modularization. The right side is after modularization.
The messy and well-organized bookshelf. The left side is before modularization. The right side is after modularization. Left Image source. Right Image source.

Hi folks! This is my first Medium post, and I hope to create even better articles to share knowledge with all of you. I welcome all feedback and suggestions.

In this article, I will share my thoughts on modularization in Flutter, which I presented to my community in a webinar session. If you would like to watch the webinar, you can check out this youtube link.

Why Flutter?

Flutter is a powerful framework for building beautiful, fast and high-performance mobile applications for both Android and iOS platforms. Even for web applications.

I have also tried creating cross-platform dashboards, including web applications using Flutter that will amaze you. If you are interested in learning more about this, please leave a comment on this Medium post and I will create an article specifically on creating web applications with Flutter. Now, back to the topic at hand.

One of the key advantages of Flutter is its ease of use and quick development cycle, which enables developers to build high-quality apps faster. However, as apps grow in size and complexity, managing the codebase becomes challenging. Modularization is a technique that can help simplify code management, improve app maintainability, and boost development productivity.

What is Modularization?

If we look at the picture of the messy bookshelf above, when we want to find a shelf-improvement book, we realize that it will be a headache to find it, because the book has not been categorized. But if we look inside a well-organized bookshelf, we can see a list of categories and we’ll see that the shelf-improvement book falls into the psychology category. That will make it easy to find the book.

Modularization is the process of dividing a large codebase into smaller, self-contained modules. Each module contains a specific set of features or functionalities that can be developed and maintained independently. By dividing the codebase into modules, developers can work on specific parts of the app without impacting other modules. This also allows developers to reuse code across different parts of the app, reducing the amount of code duplication and improving code quality.

Why is Modularization Important for Productivity?

Common structure vs Modularization structure for working together on the same project
Common structure vs Modularization structure for working together on the same project.

When we work together on the same project, especially in large teams, we often encounter dependency conflicts, build code conflicts and other issues.

However, if we use modularization by breaking down the app into smaller modules, developers can work on specific parts of the app without affecting other parts. This enables developers to work in parallel and complete tasks more quickly, reducing the time required to develop new features and improving code quality.

For example, in the Common Structure, every developer has to commit to a lib module, which can create a lot of conflicts. But in the Modularization Structure, developers can focus on the modules themselves, reducing conflicts and increasing productivity.

Secondly, modularization can help improve code readability. When a new team member is assigned to a certain module, they can explore the code more easily compared to the general structure, where new team members have to thoroughly explore the code.

Thirdly, modularization makes code reusable. When we want to enhance a particular module, it is easier to find and modify the code instead of rewriting it. Developers can create a library of reusable widgets or functions that can be used across different parts of the app, reducing code duplication and improving the app’s consistency and user experience.

How to Implement Modularization in Flutter?

Sample real case for modularization structure.
Sample real case for modularization structure.

We will create a real case by building a project with three layers with monorepo style. The main application is the first layer, the feature layer is the second layer, and the library layer is the third and final layer. The project package structure will look like this:

Project Package Structure
Project Package Structure

Every module will have a default Flutter project template. To generate a Flutter module, we can create it using the following syntax in the terminal:

flutter create --template=package name_of_module

And then, when we want to get a local library class inside the List module, how do it?

First, we can add the dependency of local inside the list pubspec.yaml and run flutter pub get. Tada, we can use the local dependency inside the list module by importing the package. That's easy, right?

But we have some problems…

When we have many modules, should it run flutter pub get for update dependency and flutter pub run build_runner build for building auto-generated code syntax for each module?

Presenting Melos

Melos is a tool for managing multi-package repositories in a monorepo style project. It allows developers to manage multiple packages within a single repository, making it easier to manage dependencies, streamline development workflows, and improve code sharing across projects. Melos also is used on popular projects such as FlutterFire. Here are some of the key benefits of using Melos:

  1. Melos makes it easier to manage dependencies across multiple packages in a project. Melos ensures that all packages in the project have the same dependencies and versions. This reduces the risk of conflicts and ensures that the project is using the latest versions of dependencies.
  2. Melos simplifies the development workflow by allowing developers to work on multiple packages within a single repository. Developers can easily run tests, build packages, and run other development tasks across all packages in the repository. This saves time and improves developer productivity.
  3. Melos allows developers to share code between packages in a project. This means that developers can avoid code duplication and improve code quality by sharing common functionality across packages. This also makes it easier to maintain consistency across projects and reduces the risk of errors.
  4. Melos is easy to set up and maintain, thanks to its simple configuration and powerful CLI. Developers can quickly create new packages, manage dependencies, and run development tasks using the Melos CLI. This reduces the time and effort required to set up and maintain a multi-package repository.

Installing Melos

To install Melos inside a Flutter modular design, you can follow these steps:

First, you need to install Melos by running the following command in your terminal:

dart pub global activate melos

Second, create melos.yaml file in the root app and then fill the file with name and package attribute, like this:

Let me explain a little bit about the attributes inside that code:

  • name is the name of the project that you first create in the project.
  • packages is a list of the paths you have created.

Now, you can initialize the workspace with the following command in your terminal:

melos bootstrap

Tada 🎉 , you have successfully initialized the workspace. For more detail about melos bootstrap you can read it here.

If you want to clean the project you can just follow the command in your terminal:

melos clean

For more detail about cleaning with melos you can read more here.

But we have other problems…

Do we have to always run flutter bootstrap if there is an auto-generated code change? If we have many modules that will take a long time.

What if we want to change only for specific modules? Are we must change to get in into the module and then run flutter pub run build_runner run each module? It will be take a much time.

Let me introduce…

Melos Custom Script

Inside of melos.yaml in the root package that we created above, we can add the scripts attribute to it, like this:

For more detail about melos custom script syntax, you can read more here.

But, how to run it?

In a terminal way, you can just type melos run [name_of_script] like this, and then you can easily select the package you want to run it in.

If you are using VS Code and you want in GUI way, you can install the Melos extensions on VS Code Marketplace.

And then you can simply click the Run script text, then you can choose the package you want to run it in.

If that works, the result will look something like this:

Custom scripts can be used for each flutter syntax, such as for testing and analysis purposes, you can create them in custom scripts.

Conclusion

Modularization is a powerful technique for managing large and complex codebases in Flutter. By dividing the app into smaller, self-contained modules, developers can work on specific parts of the app without impacting other parts. This not only improves code quality and maintainability but also boosts development productivity.

There are several approaches to implementing modularization in Flutter, including using packages and Flutter modules. By choosing the right approach, developers can optimize the app’s performance, consistency, and user experience.

Congratulations!

You have finished the modular design in Flutter. I hope you enjoyed the article. If you have any interesting topics you would like to discuss or questions, please feel free to comment below or reach out to me on my GitHub or LinkedIn.

Thank you and don’t forget to give this post a clap 👏.

--

--