Android Coden
Android 3 min lesen

Core-Module: Geteilten Code sauber strukturieren

Core-Module bündeln stabilen, wiederverwendbaren Code in einer Mehr-Modul-App. Du lernst, wie du Utilities und Design-Systeme klar abgrenzt.

Sobald eine Android-App über ein einziges Modul hinauswächst und in Feature-Module aufgeteilt wird, entsteht eine zentrale Frage: Wohin kommt der Code, der überall gebraucht wird, aber zu keiner konkreten User Journey gehört? Core-Module sind die Antwort der offiziellen Android-Architektur-Empfehlungen – sie bündeln stabilen, geteilten Code und halten gleichzeitig die Feature-Module fokussiert und schlank.

Was ist das?

Core-Module sind dedizierte Gradle-Module in einer Mehr-Modul-Android-App, die keiner einzigen Feature-Domäne gehören, aber von vielen Feature-Modulen als Abhängigkeit eingebunden werden können. Sie bilden eine eigene Schicht unterhalb der Feature-Module und oberhalb externer Bibliotheken.

Typische Vertreter sind:

  • :core:designsystem – Farben, Typografie, Compose-Theme, wiederverwendbare UI-Komponenten
  • :core:network – Retrofit- oder Ktor-Setup, Interceptoren, generische Fehlerbehandlung
  • :core:data – gemeinsame Datenmodelle, Repository-Schnittstellen, Datenbankmigrationen
  • :core:common – zustandslose Extensions, Datums- und Zahlenformatierung, rein logische Hilfsmethoden

Der Begriff „Core” signalisiert Stabilität: Dieser Code ändert sich selten und hat keine Abhängigkeit zu Feature-Modulen. Feature-Module schauen im Abhängigkeitsgraphen nach unten in Richtung Core – nie umgekehrt.

Wie funktioniert es?

In einem Gradle-Multi-Module-Projekt wird ein Core-Modul als com.android.library-Plugin angelegt, genau wie ein Feature-Modul. Feature-Module deklarieren Core-Module als implementation-Abhängigkeit in ihrer build.gradle.kts. Gradle sorgt dafür, dass nur die öffentliche API des Core-Moduls sichtbar ist – interne Implementierungsdetails bleiben verborgen.

Das Kernprinzip ist der unidirektionale Abhängigkeitsgraph: Feature-Module können Core-Module einbinden, aber Core-Module dürfen niemals Feature-Module importieren. Diese klare Einbahnstraße verhindert zyklische Abhängigkeiten, die Gradle-Builds blockieren und Testbarkeit zerstören. Du erkennst eine Verletzung dieses Prinzips sofort, wenn Gradle beim Sync eine „Circular dependency”-Warnung wirft.

Zur Laufzeit passiert nichts Besonderes – die kompilierten Klassen landen wie jeder andere Library-Code im APK oder AAB. Der Mehrwert liegt vollständig in der Build- und Entwicklungszeit: kürzere inkrementelle Kompilierung, weil sich stabile Core-Module selten ändern und im Build-Cache verbleiben, klare Eigentümerschaft für Teams, und die Möglichkeit, Core-Logik vollständig isoliert mit Unit-Tests abzusichern.

In der Praxis

Beispiel: Design-System-Modul aufsetzen

// :core:designsystem – Color.kt
package de.androidcoden.core.designsystem.theme

import androidx.compose.ui.graphics.Color

val AndroidGreen = Color(0xFF3DDC84)
val OnBackground = Color(0xFF1C1B1F)
val SurfaceLight = Color(0xFFFAFAFA)
// :core:designsystem – AppTheme.kt
@Composable
fun AppTheme(content: @Composable () -> Unit) {
    MaterialTheme(
        colorScheme = lightColorScheme(
            primary      = AndroidGreen,
            onBackground = OnBackground,
            surface      = SurfaceLight
        ),
        content = content
    )
}

Ein Feature-Modul bindet das Design-System dann ohne weiteren Aufwand ein:

// :feature:home/build.gradle.kts
dependencies {
    implementation(projects.core.designsystem)
    implementation(projects.core.common)
}

Stolperfalle: Der Core-Dump

Die größte Gefahr bei Core-Modulen ist, dass sie zu einem Sammelbecken werden. Wenn jedes neue Utility reflexartig in :core:common landet, wächst das Modul unkontrolliert – die Kompilierungszeit steigt, der Abhängigkeitsbaum wird undurchsichtig, und Code-Ownership verschwindet.

Faustregel: Ein Stück Code gehört in ein Core-Modul, wenn mindestens zwei unabhängige Feature-Module ihn tatsächlich benötigen – nicht, weil er irgendwann vielleicht nützlich sein könnte. Alles andere bleibt im Feature-Modul, bis die zweite Verwendung real auftaucht.

Ebenso gefährlich ist ein einzelnes monolithisches :core-Modul, das alle geteilten Belange vereint. Teile stattdessen nach Verantwortlichkeit auf: :core:ui, :core:network, :core:domain. So bleibt jedes Modul klein genug, um schnell zu kompilieren, und verständlich genug, um neuen Teammitgliedern sofort zu erklären, was darin zu suchen ist.

Fazit

Core-Module sind das Rückgrat jeder gut strukturierten Mehr-Modul-Android-App. Sie machen geteilten Code explizit, testbar und auffindbar – aber nur, wenn du aktiv gegen den natürlichen Hang zur Akkumulation vorgehst. Überprüfe deine Core-Module regelmäßig: Gibt es Klassen, die ausschließlich von einem einzigen Feature-Modul genutzt werden? Dann gehören sie dorthin. Führe ./gradlew :core:common:test aus, um sicherzustellen, dass deine Utilities isoliert testbar bleiben, und behandle Änderungen an Core-Modulen im Code-Review mit besonderer Sorgfalt – jede Modifikation dort wirkt sich potenziell auf die gesamte App aus.

Quellen (2)
Redaktion

Geschrieben von

Redaktion

Das Redaktionsteam recherchiert und schreibt Artikel zu aktuellen Themen rund um Tech, Lifestyle und Ratgeber.