To modularize, or not to modularize, that is the question.

Stefan M.
3 min readMay 10, 2019

--

Previously I found a discussion in my twitter feed about modularization of your Android app.

Ok ok, you are right. The topic is not really about modularization. But kind of, I would say.

Anyway. Because I’m also on the modularize train I wanted to show you how we implement the modularization and why. Because it’s not only about build speed or something. Sometimes it’s only because of proper abstraction and putting things together which belong together instead of putting everything in one big module.

In my current project we don’t write only an app but also a library which will be shared to other customers of our client when it’s done.

The requirements for this library are like this:

  • Should be named xyz-SDK (name obfuscated)
  • Can read/parse a QR Code
  • Have an API to their backend
  • Can discover “gateways” via SSDP
  • Have an API to this gateway
  • … and maybe more he haven’t told us yet 😁.

We started with the initial setup and the backend API. We put the dependencies into the build.gradle.kts file and created our clean architecture “setup”. Means we created the layer packages data and domain (presentation can be omitted in libraries 😉) and started to code.

While doing this we found out that this stuff doesn’t have to be an Android project. We could simply create a pure Kotlin project because we only do some network calls. Nothing Android SDK related. Therefore we thought we can move the current Android library to a Kotlin library.

On the other hand our app uses ProGuard/R8. Knowing the dependencies of our library (from the app perspective) and adding them to our proguard.pro file isn’t a good practice. Additionally other library users have to read the documentation carefully so that they don’t miss the part “Add this to your proguard.pro file”.

Then we decided to create a sub-module out of this library containing only the “backend API” related things.

With this approach we solved two things

  • The newly created library (backendapi-sdk) is a pure Kotlin library and doesn’t bring the “Android overhead”
  • The xyz-sdk acts as a (Android) library wrapper and declares the ProGuard related things

Users of this library don’t see anything about the backendapi-sdk cause they only declare the xyz-sdk as dependency.

For the implementation of the other requirements we followed the same pattern. Discovering gateways via SSDP shouldn’t be contained directly in the xyz-sdk, also not inside the backendapi-sdk. This feature is — logically — 100% independent from everything. Therefore our gatewaydiscover-sdk module was born. A dependency of our xyz-sdk but separated from the rest.

With this solution we have currently a hierarchy like this:

xyz-sdk/
|-- backendapi-sdk/
|-- gatewaydiscover-sdk/
|-- gatewayapi-sdk/
|-- qrcodeparser-sdk/

What we really enjoy with this solution is:

  • To have separated projects. No class in one of the sub-modules can touch a class from another sub-module.
  • The sub-modules are written in pure Kotlin.
  • We have separated dependencies. Each sub-module declares only the dependencies they really need.
  • In the future we know exactly where we have to add a feature or fix a bug.
  • … and maybe more I can’t imagine yet 😅

I really don’t want to say that this solution should be applied to all projects. This is also not an advice to you to do the same. You are free to put everything into one module and create a logical packaging. That is also absolutely fine. I only wanted to share with you what we have done and why we like this approach… and with that I want to say 👋.

--

--