Bei der Frage Sollen wir ein Monorepo für das neue (oder bestehende) Softwareentwicklungsprojekt erstellen spalten sich die Geister. Es gibt die 2 starken Lager, das eine, dass Monorepos liebt und das andere das sie verteufelt.
Wie man sich schon beim Titel des Blogposts denken kann, gehöre ich zu der Fraktion der Entwickler, die gerne in einem Monorepo arbeiten und dementsprechend möchte ich gerne meine bisherigen Erfahrungen mit Monorepos in diesem Blogpost teilen.
Bei einem Monorepo wird der Quellcode einer oder mehrerer Anwendungen oder Bibliotheken in einem einzigen Git Repository entwickelt. Im Gegensatz dazu steht die sogenannte Poly- bzw. Multirepo Strategie, bei der für jede Anwendung oder Bibliothek ein eigenes Repository angelegt wird.
Die konkrete Umsetzung des Monorepo Ansatzes ist jedem Entwicklungsteam selbst überlassen. Es kann die Anwendungen einfach nur in unterschiedlichen Ordner im selben Repository entwickeln, sich selbst ein eigenes Build System mit einem Maven Multi-Module Projekt konfigurieren oder auf ein spezielles Monorepo Tool wie z.B. Lerna oder NX zurückgreifen.
Je nach Anwendungsgebiet kann ein Monorepo mehr oder auch weniger Sinn machen. Einige Anwendungsgebiete, für die ich gerne auf den Monorepo Ansatz zurückgreife sind folgende:
Anwendungen bestehend aus einem SPA Frontend und einem Backend Wenn ich beispielsweise eine React App mit einem Spring Boot Backend entwickle, dann erstelle ich gerne eine Monorepo, um pro Feature nur einen Pull Request erstellen zu müssen, der sowohl Front- als auch Backend Änderungen beinhalten kann. Durch die Verbindung des Frontend und Backend Codes fällt es mir leicht die beiden Komponenten gemeinsam zu bauen und zu veröffentlichen.
Microservice Applications Aufbauend auf dem vorangegangenen Punkt eignet sich ein Monorepo selbstverständlich auch für eine Anwendung, die aus mehreren (Micro-) Services besteht. Hierbei fällt es leichter zu verstehen, welche Services zusammen gehören und es können sich überschneidende Logiken in eigene Bibliotheken ausgelagert und in mehreren Services eingebunden werden.
OpenSource Projekten mit mehreren Komponenten Für OpenSource Projekte kann eine Monorepo Ansatz ebenfalls von Vorteil sein, um alle zum Projekt dazugehörigen Ressourcen in einem Repository zu vereinen. Dadurch fällt es neuen Entwicklern leichter zu verstehen, wie die Anwendung aufgebaut bzw. die unterschiedlichen Komponenten zusammenhängen.
Neben den zuvor genannten Anwendungsgebieten gibt es selbstverständlich viele weitere Anwendungsgebiete, in denen ein Monorepo eingesetzt werden kann.
Bei den Anwendungsgebieten bin ich bereits kurz auf einige Vorteile von Monorepos eingegangen. Diese möchte ich hier gerne nochmals zusammenfassen und ergänzen, sowie auch auf die Nachteile von Monorepos eingehen.
Bei Miragon entscheidet jedes Projekt-Team selbst, wie es sich organisiert und welche Technologie es gerne einsetzen möchte.
Auf dem Kundenprojekt bei der Landeshauptstadt München haben wir erstmals ein Monorepo für die Entwicklung der OpenSource Prozessautomatisierungsplattform DigiWF angelegt. Das Monorepo bei der Landeshauptstadt München beschreibe ich in einem noch folgenden Blogpost näher.
Nachdem wir erste erfolgreiche Versuche mit einem Monorepo bei der Landeshauptstadt München machen konnten, haben wir uns beim Projekt Miranum-IDE ebenfalls dazu entschieden ein Monorepo anzulegen und dort die VS-Code Extensions sowie eine CLI App für die Prozessentwicklung zu entwickeln. Über dieses Projekt werde ich ebenfalls zeitnah einen Blogpost veröffentlichen.
Bei der Umsetzung eines Monorepos gibt es einige Punkte, die man beachten sollte, um das Team mitzunehmen und eine gute Softwareentwicklungsexperience zu schaffen.
In einem Monorepo sollten die Befehle für Builds, das Ausführen von Tests, etc. einheitlich und für die gesamte Codebasis ausführbar sein. Insbesondere wenn unterschiedliche Technologien (z.B. Java und TypeScript) in einem Projekt eingesetzt werden, sollte man sich intensiv Gedanken darüber machen welche Build Tools für die beiden Sprachen verwendet werden sollen und ob bzw. wie man diese am besten miteinander integrieren kann. Beispielsweise könnte man den TypeScript-Build mit in den Maven Build Cycle integrieren. Dadurch können auch Entwickler, die nur an einem bestimmten Teil des Monorepos arbeiten die Tests oder den Build für alle Anwendungen ausführen. Zusätzlich können diese einheitlichen Befehle wiederum in den CI/CD Pipelines wiederverwendet werden, wodurch sich die Konfiguration dieser etwas einfacher gestaltet.
Die Dokumentation der Module und Anwendungen, die im Monorepo entwickelt werden sollte möglichst früh begonnen werden, damit jeder (neue) Entwickler nachlesen kann wie die einzelnen Komponenten zusammenhängen.
Die Umsetzung des Monorepos sollte das Team gemeinsam machen und Entscheidungen zu Tools, der Struktur, etc. gemeinsam getroffen werden. Bei uns hat sich hierbei der Ansatz etabliert, dass einzelne Personen einen Vorschlag ausarbeiten und diesen dann vorstellen und das Team nach dem Ansatz der integrativen Entscheidungsfindung über den Vorschlag abstimmt.
Es gibt viele gute Gründe, die für Monorepos sprechen. Ebenso gibt es viele Gründe, die dagegen sprechen. Am Ende ist es eine Glaubensfrage, die jedes Team für sich selbst entscheiden sollte. Ich persönlich arbeite gerne in Monorepos, da mich der Dschungel an Repositories stört, der häufig entsteht, wenn ein Projekt wächst und immer neue Services dazukommen.
Rechtliches