Blog Infos
Modularization Mindset
  • Build time: It takes forever and a day to compile and build your project.
  • Reusability: You need to share some of your Features among multiple apps.
  • Maintenance: There is no Separation of Concern. A big, spaghetti codebase that each Feature has many side effects on the other ones. also, it appears that your colleagues are not into respecting SOLID principles in action and be willing to open PRs that contain logic that accesses the world as a whole.
  • Test: You can’t write a simple test scenario for a self-contained Feature, and you need to mock the whole world.
  • Demo Apps: You are fed up with running the entire project for a slight change, and you have no idea how to run only a single Feature isolated from the whole app.
Layer vs. Feature Separation
Gradle Incremental Build
//App dependencies in Build.gradle
implementation project(path: ':feature1')
implementation project(path: ':feature2')
//Feature1 dependencies in Build.gradle
implementation project(path: ':core')
//Feature2 dependencies in Build.gradle
implementation project(path: ':core')
//Core dependencies in Build.gradle
api project(path: ':location')
api project(path: ':network')
api project(path: ':resources')

So let’s change a line of code in the Location module. We have an apidependency for Location, and not only dit it exposed to the Core module but it is also exposed to Feature1 and Feature2. So by modifying a module in this hierarchy, Gradle will recompile four modules. You can track compile tasks by searching “compileDebugKotlin” in your build window (the project is written with Kotlin).


How Gradle recompiles modules after a modification into a module that is exposed to its top layer

Job Offers

Job Offers

    Talent Acquisition Manager – Technology

    New York, NY; Atlanta, GA
    • Full Time
    apply now

    Senior Compiler Engineer C++/LLVM – Leuven

    Leuven, Belgium
    • Full Time
    apply now

    Engineering Manager – Apps Lifecycle

    Zalando SE
    • Full Time
    apply now
Load more listings



Is Your App Modular?

In this talk, we will see the common reasons for splitting an android application into modules and a general overview of the modules structure. How multi-modularity can lead to a stricter architecture and enhance reusability…
Watch Video

Is your App Modular?


Circular Dependencies
FAILURE: Build failed with an exception.
* What went wrong:
Circular dependency between the following tasks: ....
  • Step 1: Create three new modules: feature1_api, feature2_api, and shared
  • Step 2: Implement feature1_api and shared dependency inside feature1.
  • Step 3: Implement feature2_api and shared dependency inside feature2.
  • Step 4: Move all common Android resources between feature1 and feature2to the shared module.
  • Step 5: Move all common utils and helpers classes between feature1 and feature2 to the shared module.
  • Step 6: Find all common model/entity classes between feature1 and feature2. If the common model/entity belongs to feature1’s responsibility, move it to feature1_api. Do this for feature2 too.
  • Step 7: Find all common interfaces classes between feature1 and feature2. If the common interface belongs to feature1’s responsibility, move it to feature1_api. Do this for feature2 too.
  • Step 8: Find all other common concrete classes (fully implemented) between feature1 and feature2. If the common class belongs to feature1’s responsibility, extract an interface out of its public functions, and move it to feature1_api. Do this for feature2 too.
  • Step 9: Refactor all dependency injections related to feature1 and feature2and use the new interfaces (created in the previous step) instead of the concrete one (in Dagger, you can add a new @Binds for each interface).

Resolving circular dependencies by adding API, Impl, and shared modules.

Dynamic Features
  • Layer-Based by structural isolation
  • Feature-Based by onDemand delivery

Gradle Feature modules vs on-demand Feature modules

  • Navigation: Your features are not visible to each other. Also, the app has no idea about the features that led to using some weird solutions like Reflection, Deeplink, and BroadcastReceivers.
  • Singleton Objects: like Database, you should decide whether you want only one DB for all modules or one DB per Feature.
Gradle Build Scripts
  • The Definition of a Feature
  • Everything is an API.
  • Multiple official and test Apps
  • TDD Feature Development



Managing dependencies in a single module project is pretty simple, but when you start…

Running Instrumented Tests in a Gradle task

During the latest Google I/O, a lot of great new technologies were shown. The…

The ABC of Modularization for Android in 2021

Modularization is not a recent topic at all. This concept have been around us…
Mobile device concept is one step ahead of the trend in technology, bringing an…

2 Comments. Leave new

  • Hamed Rahimvand
    16.02.2022 9:28

    Well done Ehsan.

  • Sebastian Helzer
    17.02.2022 19:05

    I love this article! My one question is how do you avoid having test Apps (demos, samples) adding to the build time? They want to compile when I’m building the real app in CI.

Leave a Reply

Your email address will not be published.

Fill out this field
Fill out this field
Please enter a valid email address.