0Pricing
Android Academy · Lesson

Why Modularize

Build speed, ownership and reuse.

Why Modularize is a free Android Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The Monolith Problem

When an Android app grows, all its code often lives in a single app module. This is a monolith. At first it is convenient, but over time it becomes painful: every change touches the same module, builds get slow, and team members constantly step on each other.

Modularization means splitting that one big module into many smaller, focused Gradle modules. In this lesson you will learn why teams do this and what concrete benefits it brings.

What a Module Actually Is

In Gradle, a module is an independently buildable unit of code with its own build.gradle.kts file. Your app already has at least one: the :app module. You declare every module in settings.gradle.kts.

Adding a module is as simple as including it. Each module produces its own build output and can depend on other modules.

// settings.gradle.kts
include(":app")
include(":core:designsystem")
include(":core:data")
include(":feature:home")
include(":feature:profile")

Benefit 1: Faster Builds

The biggest practical win is build speed. Gradle can build modules in parallel and, crucially, cache and skip modules whose inputs did not change.

If you edit only :feature:profile, Gradle reuses the already-built outputs of every other module. In a monolith, any change can force a recompile of the whole app.

  • Parallel execution across modules
  • Incremental builds: only rebuild what changed
  • Better remote/build cache hit rates
// gradle.properties
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true

Benefit 2: Clear Boundaries

Modules enforce boundaries. Code in one module can only see what another module deliberately exposes. This prevents the tangled spaghetti where every class reaches into every other class.

You control visibility with the api vs implementation Gradle configurations. implementation keeps a dependency private to the module; consumers cannot accidentally use it.

// feature/profile/build.gradle.kts
dependencies {
    // Exposed to whoever depends on :feature:profile
    api(project(":core:model"))

    // Private: hidden from consumers of this module
    implementation(project(":core:network"))
}

Benefit 3: Reuse

Once logic lives in a focused module, you can reuse it anywhere. A :core:designsystem module holding your theme, colors and reusable composables can be shared by every feature.

The same idea scales to multiple apps: a company can share a :core:network module across several products instead of copying code.

// Any feature can pull in shared building blocks
// feature/home/build.gradle.kts
dependencies {
    implementation(project(":core:designsystem"))
    implementation(project(":core:data"))
}

Benefit 4: Team Ownership

Modules map neatly to team ownership. The payments team owns :feature:payments; the profile team owns :feature:profile. They can work in parallel with fewer merge conflicts because their code lives in separate folders and build files.

Tools like a CODEOWNERS file can automatically request reviews from the right team based on the module path.

# .github/CODEOWNERS
/feature/payments/   @org/payments-team
/feature/profile/    @org/profile-team
/core/designsystem/  @org/platform-team

Benefit 5: Encapsulation by Visibility

Inside a module, Kotlin's internal modifier becomes powerful. An internal class or function is visible only within its own module. Other modules literally cannot reference it.

This lets you expose a small public surface and hide the implementation details, which is impossible to enforce in a single giant module.

// In :core:data
// Public API other modules may use
fun interface UserRepository {
    suspend fun loadUser(id: String): User
}

// Hidden from other modules
internal class DefaultUserRepository(
    private val api: UserApi
) : UserRepository {
    override suspend fun loadUser(id: String) = api.fetch(id).toUser()
}

The Cost: Some Overhead

Modularization is not free. Each module adds a build.gradle.kts to maintain, and you must think about which module owns each piece of code. Over-modularizing a tiny app creates busywork without payoff.

The rule of thumb: modularize when build times hurt, when teams collide, or when you have clear reusable layers. A weekend hobby app rarely needs 30 modules.

A Typical Module Layout

A common, scalable structure splits modules into app, feature, and core layers. The :app module wires everything together; features hold user-facing screens; core modules hold shared infrastructure.

// Conceptual project tree
// app/                  <- single entry point, wires features
// feature/
//   home/
//   profile/
//   settings/
// core/
//   designsystem/       <- theme + reusable composables
//   data/               <- repositories
//   network/            <- Retrofit/Ktor
//   model/              <- shared data classes

Convention Plugins Keep It Sane

With many modules, copy-pasting the same Gradle setup everywhere is a trap. Teams extract shared configuration into convention plugins (in a build-logic module). Each real module then applies one plugin instead of repeating dozens of lines.

You will see this pattern in large open-source apps like Now in Android. For now, just know the goal: keep build files small and consistent.

// feature/home/build.gradle.kts
plugins {
    // One convention plugin sets up Android + Compose + Kotlin
    id("myapp.android.feature")
}

android { namespace = "com.myapp.feature.home" }

Mindset: Think in Layers

The single most useful mental model: dependencies should flow downward. Features depend on core; core does not depend on features. The :app module sits at the very top and depends on everything it needs to assemble the app.

If you keep this direction consistent, your module graph stays clean and you avoid cycles, which you will explore in a later lesson.

// Allowed:  app -> feature -> core
// Forbidden: core -> feature (upward) or feature -> feature (sideways)
// app/build.gradle.kts
dependencies {
    implementation(project(":feature:home"))
    implementation(project(":feature:profile"))
}

Quick Check

Which of the following is the most concrete, everyday benefit teams get from modularizing a growing Android app?

Recap: Why Modularize

You learned why teams break a monolith into modules:

  • Faster builds via parallel execution and incremental caching
  • Clear boundaries using api/implementation and internal
  • Reuse of core layers like design system and network
  • Team ownership with fewer merge conflicts

You also saw the cost (extra build files) and the golden rule: dependencies flow downward, app -> feature -> core. Next, you will draw the actual boundaries between feature and core modules.

Frequently asked questions

Is the “Why Modularize” lesson free?

Yes — the full text of “Why Modularize” is free to read here on the web, and the Android Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Android Academy course, upgrade to CoddyKit PRO.

What will I learn in “Why Modularize”?

Build speed, ownership and reuse. You practise Android Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Android Academy?

No prior experience is required. Android Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Why Modularize” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Android Academy lesson?

Yes. Every Android Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Why Modularize
  2. Feature and Core Modules
  3. Managing Module Dependencies
  4. Navigation Across Modules
← Back to Android Academy