Note: This post is a tidied up version of my answer to a StackOverflow question about structuring multi-module apps.
Transitioning to a multi-module project is an excellent way to increase code reuse, optimise build times (unchanged modules aren’t recompiled), and ensure your app’s structure is logical. Your core goal is to make your
appmodule as small as possible, as it will be recompiled every time.
We used a few general principles, which may help you:
- A common
base-uimodule contains the primary
- Other front-end modules (
dashboard, etc) implement this
- Libraries that will be used in all user-facing modules are included in
base-ui, as an
- Libraries that are only used in some modules are dependencies only in those modules.
- The project makes extensive use of data syncing etc too, so there are also
dashboard-dataetc modules, following the same logic.
dashboardfeature module depends on
appmodule depends only on feature modules,
I strongly suggest sketching out your module dependency flow beforehand, we ended up with ~15 or so modules, all strictly organised. In your case, you mentioned it’s already quite a large app, so I imagine
app needs feature modules pulled out of it, as does
domain. Remember, small modules mean less code recompiled!
We encountered some issues with making sure the same version (
flavors) of the app is used across all submodules. Essentially, all submodules have to have the same
buildTypes defined as the
On the other side of the coin, multi module development does really make you think about dependencies, and enforces strict separation between features. You’re likely to run into a few unexpected problems that you’ve never considered before. For example, something as simple as displaying the app’s version suddenly complicates.
This article also helped us decide on our approach. There are other excellent articles around nowadays, which I wish had existed when we’d transitioned!
Here’s an example diagram for an app I’m currently working on. Whilst it is far from perfect (the real world unfortunately intrudes!), all of the principles outlined above are visible:
Note that distinguishing between
implementation would be a good next step for a diagram like this, so that dependencies are more obvious.