Einleitung: Was ist ein Monorepository und warum braucht ein Kotlin-Entwickler es?
Ein Monorepository (Monorepo) ist ein Ansatz, bei dem der Code mehrerer Projekte oder Module in einem einzigen Repository gespeichert wird. Im Kontext von Kotlin ist dies besonders praktisch: Sie können den Serverteil (Ktor), Bibliotheken, CLI-Tools und sogar mobile Anwendungen (Kotlin Multiplatform) in einer einzigen Struktur vereinen. Für Anfänger vereinfacht ein Monorepository die Navigation, das Testen und die Zusammenarbeit.
In diesem Artikel werden wir besprechen, wie man ein Monorepository mit Kotlin unter Verwendung von Gradle Multi-Project Build organisiert. Sie erfahren, wie Sie Ordner richtig strukturieren, Abhängigkeiten konfigurieren und typische Fehler vermeiden.
Hauptteil: Erstellung eines Monorepositorys mit Kotlin
1. Struktur des Monorepositorys: Grundprinzipien
Die richtige Struktur ist der Schlüssel zum Erfolg. In einem Kotlin-Monorepository ist jedes Modul ein separates Gradle-Unterprojekt. Hier ist ein typisches Schema:
my-monorepo/├── build.gradle.kts # Root-Build-Datei├── settings.gradle.kts # Modulkonfiguration├── gradle.properties # Gemeinsame Eigenschaften├── shared/ # Gemeinsame Bibliothek (Modul)│ ├── build.gradle.kts│ └── src/│ └── main/│ └── kotlin/│ └── com/example/shared/│ └── Utils.kt├── backend/ # Server-Modul (Ktor)│ ├── build.gradle.kts│ └── src/│ └── main/│ └── kotlin/│ └── com/example/backend/│ └── Application.kt└── cli-tool/ # CLI-Tool ├── build.gradle.kts └── src/ └── main/ └── kotlin/ └── com/example/cli/ └── Main.ktDie goldene Regel: Ein Modul – eine Verantwortung. Mischen Sie nicht Geschäftslogik und Infrastruktur in einem Modul. Dies vereinfacht das Testen und die Wiederverwendung von Code.
2. Gradle-Konfiguration für das Monorepository
Beginnen wir mit der Root-Datei settings.gradle.kts. Sie definiert, welche Module zum Projekt gehören:
// settings.gradle.ktsrootProject.name = "my-monorepo"
include(":shared")include(":backend")include(":cli-tool")
// Optional: Modulnamen können über include() vergeben werden// include(":libs:utils") – wenn das Modul im Ordner libs verschachtelt istJetzt die Root-build.gradle.kts. Normalerweise enthält sie nur allgemeine Einstellungen (Plugins, Repositories) und hat keinen eigenen Code:
// build.gradle.kts (Root)plugins { kotlin("jvm") version "1.9.22" apply false id("application") apply false}
allprojects { repositories { mavenCentral() }}
subprojects { apply(plugin = "kotlin") // Gemeinsame Einstellungen für alle Unterprojekte dependencies { implementation(kotlin("stdlib")) }}Beachten Sie apply false – dies verhindert die Anwendung des Plugins auf das Root-Projekt. Jedes Modul entscheidet selbst, welche Plugins es benötigt.
3. Beispiel eines Moduls: Gemeinsame Bibliothek (shared)
Das Modul shared enthält wiederverwendbare Funktionen. Seine build.gradle.kts:
// shared/build.gradle.ktsplugins { kotlin("jvm")}
dependencies { // Keine internen Abhängigkeiten – dies ist ein Basismodul testImplementation("org.jetbrains.kotlin:kotlin-test")}Der Code selbst in Utils.kt:
// shared/src/main/kotlin/com/example/shared/Utils.ktpackage com.example.shared
fun greet(name: String): String = "Hello, $name!"
fun add(a: Int, b: Int): Int = a + bDieses Modul kann nun mit anderen Modulen verbunden werden:
// backend/build.gradle.ktsplugins { kotlin("jvm") id("application")}
dependencies { implementation(project(