Blog Infos
Author
Published
Topics
,
Published
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

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

,

Modularization – flatten your graph and get the real benefits

The story of improving modularization in multiple projects with 15+ contributing teams, hundreds of modules with complex module structure and how making order in the module graph brings the benefits from the modularization to your…
Watch Video

Modularization - flatten your graph and get the real benefits

Josef Raska
Android Engineer
Glovo

Modularization - flatten your graph and get the real benefits

Josef Raska
Android Engineer
Glovo

Modularization - flatten your graph and get the real benefits

Josef Raska
Android Engineer
Glovo

Jobs

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
Conclusion
  • The Definition of a Feature
  • Everything is an API.
  • Multiple official and test Apps
  • TDD Feature Development

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

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

Running Instrumented Tests in a Gradle task

During the latest Google I/O, a lot of great new technologies were shown. The…
READ MORE
blog
Many of us have faced Groovy difficulties and used to convert it to Kotlin…
READ MORE
blog
Modularization has become an essential part of Mobile Development at scale, however it isn’t…
READ MORE

3 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.

  • Zokrijon
    29.09.2022 7:31

    This is the article I’ve been looking for. Found answers to all my questions related to modularization. Thanks a lot.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

Menu