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

Einleitung: Was ist ein Monorepository und warum wird es in Java benötigt



In der Java-Entwicklung gibt es zwei Hauptansätze zur Speicherung von Code: Monorepository (Monorepo) und Multirepository (Multirepo). Ein Monorepository ist eine Strategie, bei der alle Codebasen eines Projekts (Bibliotheken, Dienste, Hilfsprogramme, Konfigurationen) in einem einzigen Repository gespeichert werden. Für Java-Entwickler, die mit großen Unternehmenssystemen oder Microservices arbeiten, wird das Monorepository zunehmend zu einer beliebten Lösung.



Die Vorteile eines Monorepositorys in Java liegen auf der Hand:

  • Einheitliche Abhängigkeitsversionen: Alle Module verwenden eine Version der Bibliotheken, was Konflikte (classpath hell) ausschließt.
  • Vereinfachtes Refactoring: Eine API-Änderung in einem Modul ist sofort in allen abhängigen Modulen sichtbar.
  • Durchgängiger Änderungsverlauf: Ein einzelner Commit kann Änderungen in mehreren Modulen enthalten, was das Debugging vereinfacht.
  • Standardisierung: Einheitliche Regeln für Codestil, Linting und CI/CD für das gesamte Projekt.


Ein Monorepository erfordert jedoch eine durchdachte Organisation. In diesem Artikel werden wir uns ansehen, wie man ein Java-Projekt in einem Monorepository mit Maven und Gradle richtig strukturiert.



Hauptteil: Organisation eines Monorepositorys in Java



1. Verzeichnisstruktur: Modularer Ansatz



Die Grundlage eines Monorepositorys ist eine modulare Struktur. Jedes Modul stellt eine unabhängige Einheit dar (Bibliothek, Dienst, Hilfsprogramm). Betrachten wir eine typische Struktur für ein Java-Projekt:



my-monorepo/├── build.gradle          # Root-Build-Datei (Gradle)├── settings.gradle       # Liste der Module├── gradle.properties     # Gemeinsame Einstellungen├── gradle/│   └── wrapper/├── common/               # Gemeinsame Bibliotheken│   ├── common-utils/     # Hilfsprogramme (Strings, Datumsangaben)│   └── common-dto/       # DTOs für den Datenaustausch├── services/             # Microservices│   ├── user-service/     # Benutzerservice│   └── order-service/    # Bestellservice├── libs/                 # Interne Bibliotheken│   └── logging-lib/      # Logging-Bibliothek├── tests/                # Integrations-/End-to-End-Tests│   └── e2e-tests/└── buildSrc/             # Gemeinsame Plugins und Konfigurationen


Jedes Modul hat intern eine Standard-Maven/Gradle-Struktur:

user-service/├── build.gradle├── src/│   ├── main/│   │   ├── java/│   │   │   └── com/example/user/│   │   │       ├── controller/│   │   │       ├── service/│   │   │       └── repository/│   │   └── resources/│   │       └── application.yml│   └── test/│       └── java/└── Dockerfile


2. Abhängigkeitsverwaltung: Maven BOM und Gradle Version Catalog



Das Hauptproblem eines Monorepositorys ist die Synchronisation der Abhängigkeitsversionen. In Java wird dies auf zwei Arten gelöst.



Variante 1: Maven BOM (Bill of Materials)

Es wird ein Root-POM erstellt, das alle Versionen der Abhängigkeiten deklariert. Untergeordnete Module verwenden dependencyManagement:



<!-- pom.xml (Root) --><dependencyManagement>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-dependencies</artifactId>            <version>3.2.0</version>            <type>pom</type>            <scope>import</scope>        </dependency>        <dependency>            <groupId>com.example</groupId>            <artifactId>common-utils</artifactId>            <version>1.0.0</version>        </dependency>    </dependencies></dependencyManagement>


Variante 2: Gradle Version Catalog

In der Datei gradle/libs.versi

Blogs

Buchempfehlungen