Monorepository mit Kotlin: Code-Organisation in der Praxis

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

Einleitung: Warum ein Monorepository in Kotlin?

\n

In der modernen Kotlin-Entwicklung stellt sich oft die Frage: Soll man mehrere zusammenhängende Projekte (Backend, Microservices, Bibliotheken, Android-Apps) in separaten Repositories (Polyrepository) oder in einem einzigen Monorepository zusammenfassen? Ein Monorepository ist eine Strategie zur Codeverwaltung, bei der sich alle Komponenten in einem einzigen Versionskontrollsystem befinden. Für Kotlin-Projekte ist dies aufgrund des leistungsstarken Build-Systems Gradle und der integrierten Unterstützung für Multi-Modularität besonders relevant.

\n

In diesem Artikel behandeln wir die praktischen Aspekte der Organisation eines Monorepositorys mit Kotlin: von der Verzeichnisstruktur bis zur Konfiguration von CI/CD und der Verwaltung von Abhängigkeiten. Sie erfahren, wie Sie typische Fehler vermeiden und den größtmöglichen Nutzen aus einem einheitlichen Code-Repository ziehen.

\n\n

1. Struktur des Monorepositorys: Von der Theorie zur Praxis

\n

Die richtige Struktur ist die Grundlage eines erfolgreichen Monorepositorys. Betrachten wir ein typisches Projekt, das eine REST-API mit Ktor, eine Bibliothek für die Datenbankarbeit und eine Android-App umfasst. Hier ist die empfohlene Hierarchie:

\n
my-monorepo/\n├── build.gradle.kts          # Root-Build-Datei\n├── settings.gradle.kts       # Modulkonfiguration\n├── gradle.properties         # Gemeinsame Eigenschaften\n├── gradle/\n│   └── libs.versions.toml    # Versionskatalog (Version Catalog)\n├── libs/                     # Gemeinsame Bibliotheken\n│   ├── common-utils/         # Hilfsprogramme, Erweiterungen\n│   ├── common-db/            # Datenbankarbeit (Exposed)\n│   └── common-dto/           # Data Transfer Objects\n├── services/                 # Serveranwendungen\n│   ├── user-service/         # Benutzer-Microservice\n│   └── order-service/        # Bestell-Microservice\n└── apps/                     # Client-Anwendungen\n    └── android-app/          # Android-App\n
\n

Das Schlüsselelement ist settings.gradle.kts. Es bindet alle Module ein:

\n
rootProject.name = "my-monorepo"\n\ninclude("libs:common-utils")\ninclude("libs:common-db")\ninclude("libs:common-dto")\ninclude("services:user-service")\ninclude("services:order-service")\ninclude("apps:android-app")\n
\n

Eine solche Struktur ermöglicht die einfache Wiederverwendung von Code zwischen Diensten und Client sowie die zentrale Verwaltung von Abhängigkeitsversionen.

\n\n

1.1. Version Catalog: Abhängigkeitsverwaltung

\n

In einem Monorepository ist es entscheidend, die Duplizierung von Bibliotheksversionen zu vermeiden. Verwenden Sie den Version Catalog (Datei gradle/libs.versions.toml):

\n
[versions]\nkotlin = "2.0.21"\nktor = "3.0.3"\nexposed = "0.57.0"\n\n[libraries]\nktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }\nexposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" }\n\n[plugins]\nkotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }\n
\n

Jetzt können Sie in jedem Modul schreiben:

\n
dependencies {\n    implementation(libs.ktor.server.core)\n    implementation(libs.exposed.core)\n}\n
\n

Dies stellt sicher, dass alle Module dieselben Versionen verwenden, und vereinfacht Massenaktualisierungen.

\n\n

2. Praktische Modulorganisation: Gradle Multi-Project

\n

Jedes Modul des Monorepositorys ist ein separates Gradle-Unterprojekt mit seiner eigenen build.gradle.kts. Betrachten wir die Konfiguration der Bibliothek common-utils:

\n
// libs/common-utils/build.gradle.kts\nplugins {\n    alias(libs.plugins.kotlin.jvm)\n}\n\ngroup = "com.mycompany.common"\nversion = "1.0.0"\n\ndependencies {\n    implementation(kotlin("stdlib"))\n    implementation(libs.kotlinx.coroutines)\n}\n
\n

Und hier ein typischer Microservice mit Ktor:

\n
// services/user-service/build.gradle.kts\nplugins {\n    alias(libs.plugins.kotlin.jvm)\n    alias(libs.plugins.ktor)\n}\n\ndependencies {\n    implementation(project(":libs:common-utils"))\n    implementation(project(":libs:common-dto"))\n    impl                

Blogs

Buchempfehlungen