Monorepository mit Kotlin: Code-Organisation und Best Practices

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Monorepository mit Kotlin: Code-Organisation und Best Practices



Mit dem Wachstum von Projekten und der zunehmenden Anzahl von Diensten stehen Entwickler vor der Frage: Wie organisiert man Code so, dass er verwaltbar, leicht testbar und schnell bereitstellbar bleibt? Ein beliebter Ansatz ist das Monorepository (Monorepo). In diesem Artikel werden wir untersuchen, wie man ein Monorepository mit Kotlin und Gradle effektiv organisiert, welche Tools und Patterns man verwendet und wie man typische Fehler vermeidet.



Was ist ein Monorepository und warum wird es benötigt?



Ein Monorepository ist ein Ansatz, bei dem der Code mehrerer Projekte (Module, Bibliotheken, Dienste) in einem einzigen Repository gespeichert wird. Im Kontext von Kotlin bedeutet dies, dass Sie ein gemeinsames Gradle-Projekt haben können, das Module für Backend-Dienste, Android-Apps, gemeinsame Bibliotheken und sogar Dokumentation enthält.



Vorteile eines Monorepository:

  • Einheitliche Versionierung — alle Module verwenden dieselbe Kotlin-Version und gemeinsame Abhängigkeiten.
  • Vereinfachtes Refactoring — Änderungen in einer gemeinsamen Bibliothek sind sofort für alle Konsumenten sichtbar.
  • Gemeinsame CI/CD-Konfiguration — eine Pipeline für alle Module.
  • Verbesserte Zusammenarbeit — Entwickler sehen den gesamten Code des Projekts.


Allerdings erfordert ein Monorepository Disziplin: Ohne richtige Organisation kann es sich in einen „Monolithen“ mit verworrenen Abhängigkeiten verwandeln. Kotlin und Gradle bieten hervorragende Werkzeuge, um dem entgegenzuwirken.



Struktur eines Monorepository mit Kotlin



Betrachten wir eine typische Projektstruktur mit einem Backend-Dienst auf Ktor, einer gemeinsamen Bibliothek für Datenmodelle und einer Android-App:



my-monorepo/├── build.gradle.kts          # Root-Build-Datei├── settings.gradle.kts       # Moduleinbindung├── gradle.properties         # Gemeinsame Versionen├── common/│   ├── build.gradle.kts│   └── src/│       └── main/kotlin/│           └── com/example/common/│               └── Models.kt├── backend/│   ├── build.gradle.kts│   └── src/│       └── main/kotlin/│           └── com/example/backend/│               └── Application.kt├── android-app/│   ├── build.gradle.kts│   └── src/│       └── main/kotlin/│           └── com/example/android/│               └── MainActivity.kt└── ci/    └── build.sh


Die Datei settings.gradle.kts bindet die Module ein:



rootProject.name = "my-monorepo"

include(":common")include(":backend")include(":android-app")


Das Root-build.gradle.kts enthält normalerweise nur gemeinsame Plugins und Einstellungen:



plugins {    kotlin("jvm") version "1.9.22" apply false    kotlin("android") version "1.9.22" apply false    id("org.jetbrains.kotlin.plugin.serialization") version "1.9.22" apply false}

allprojects { group = "com.example" version = "1.0.0"}


Wichtig: Plugins werden mit apply false angegeben, damit sie nicht auf das Root-Projekt angewendet werden, sondern für die untergeordneten Module verfügbar sind.



Abhängigkeitsverwaltung im Monorepository



Eine der Hauptaufgaben ist es, die Duplizierung von Abhängigkeitsversionen zu vermeiden. Dazu wird der Gradle Version Catalog verwendet (Datei libs.versions.toml im Ordner gradle). Beispiel:



# gradle/libs.versions.toml[versions]kotlin = "1.9.22"ktor = "2.3.7"coroutines = "1.7.3"

[libraries]ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }ktor-server-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" }kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }

[plugins]kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.

Blogs

Buchempfehlungen