Monorepository mit Java: 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

Monorepository mit Java: Code-Organisation in der Praxis

\n

In der modernen Java-Entwicklung stellt sich immer häufiger die Frage der Wahl zwischen einem Monorepository (Monorepo) und mehreren einzelnen Repositories. Ein Monorepository ist ein Ansatz, bei dem der gesamte Code eines Projekts (mehrere Dienste, Bibliotheken, Konfigurationen) in einem einzigen Git-Repository gespeichert wird. In diesem Artikel werden wir uns ansehen, wie man ein Monorepository mit Java in der Praxis organisiert: von der Ordnerstruktur bis zur Einrichtung von Build und CI/CD. Sie erhalten fertige Codebeispiele und Empfehlungen, die Ihnen helfen, typische Fehler zu vermeiden.

\n\n

Warum ein Monorepository für Java?

\n

Ein Monorepository ist besonders nützlich für Java-Projekte, bei denen viele Module voneinander abhängen. Die wichtigsten Vorteile:

\n
    \n
  • Einheitliche Abhängigkeitsversion – alle Module verwenden dieselbe Version von Bibliotheken, was Konflikte ausschließt.
  • \n
  • Vereinfachtes Refactoring – eine Änderung der API in einem Modul ist sofort in allen abhängigen Modulen sichtbar.
  • \n
  • Gemeinsame Build-Konfiguration – Gradle oder Maven werden einmal für alle Module konfiguriert.
  • \n
  • Integrität von CI/CD – eine Pipeline für alle Dienste, Änderungen sind leichter nachvollziehbar.
  • \n
\n

Allerdings erfordert ein Monorepository Disziplin: Ohne eine klare Struktur wird es chaotisch. Betrachten wir die richtige Organisation.

\n\n

Struktur eines Monorepositorys für ein Java-Projekt

\n

Empfohlene Struktur für ein Monorepository mit Java (am Beispiel von Gradle):

\n
my-monorepo/\n├── build.gradle.kts          # Root-Build-Datei\n├── settings.gradle.kts       # Bindet alle Module ein\n├── gradle.properties         # Gemeinsame Eigenschaften\n├── libs/                     # Gemeinsame Bibliotheken\n│   ├── common-utils/\n│   │   ├── build.gradle.kts\n│   │   └── src/\n│   └── logging/\n│       ├── build.gradle.kts\n│       └── src/\n├── services/                 # Microservices\n│   ├── user-service/\n│   │   ├── build.gradle.kts\n│   │   └── src/\n│   └── payment-service/\n│       ├── build.gradle.kts\n│       └── src/\n├── config/                   # Konfigurationen (z. B. checkstyle, spotbugs)\n│   └── checkstyle.xml\n└── docker/                   # Dockerfile für jeden Dienst\n    ├── user-service.Dockerfile\n    └── payment-service.Dockerfile\n
\n

Wichtige Prinzipien:

\n
    \n
  • Module werden in libs (Bibliotheken) und services (ausführbare Anwendungen) unterteilt.
  • \n
  • Das root-build.gradle.kts definiert gemeinsame Plugins und Versionen.
  • \n
  • Die Datei settings.gradle.kts bindet alle Unterprojekte ein.
  • \n
\n

Beispiel für settings.gradle.kts:

\n
rootProject.name = "my-monorepo"\n\ninclude(\n    "libs:common-utils",\n    "libs:logging",\n    "services:user-service",\n    "services:payment-service"\n)\n
\n\n

Einrichtung von Abhängigkeiten zwischen Modulen

\n

Die Hauptaufgabe eines Monorepositorys ist die Verwaltung interner Abhängigkeiten. Betrachten wir ein Beispiel, bei dem user-service von common-utils abhängt.

\n

Schritt 1. In der root-gradle.properties deklarieren wir Versionen:

\n
# gradle.properties\nkotlinVersion=1.9.0\nspringBootVersion=3.2.0\ncommonUtilsVersion=1.0.0\n
\n

Schritt 2. In der root-build.gradle.kts binden wir Plugins ein und legen gemeinsame Einstellungen fest:

\n
plugins {\n    id("java-library") apply false\n    id("org.springframework.boot") version "3.2.0" apply false\n    id("io.spring.dependency-management") version "1.1.4" apply false\n}\n\nallprojects {\n    group = "com.example"\n    version = "1.0.0"\n\n    repositories {\n        mavenCentral()\n    }\n}\n\nsubprojects {\n    apply(plugin = "java-library")\n\n    java {\n        sourceCompatibility = JavaVersion.VERSION_17\n        targetCompatibility = JavaVersion.VERSION_17\n    }\n\n    dependencies {\n        implementation("org.slf4j:slf4j-api:2.0.9")\n        testImplementation("org.j                

Blogs

Buchempfehlungen