Every large mobile codebase eventually hits the wall: build times crawl, merge conflicts multiply, and one team's change breaks another team's feature. Modularization is the usual prescription — but it's easy to get wrong.
Start with the why, not the how
Teams often modularize by layer (:data, :domain, :ui) when their actual pain is team coupling. If two squads keep stepping on each other, split by feature, not layer.
The rules that worked for us
- Feature modules never depend on each other — only on API modules
- Each module owns its DI graph
- Navigation is decoupled through a routing contract
// A feature exposes only its contract
interface CheckoutApi {
fun launchCheckout(cart: CartId): Intent
}
What I'd do differently
Measure build times before starting, and set a target. Modularization without measurement is architecture theater.