Monorepository mit C#: Code-Organisation und Best Practices
In der modernen C#-Entwicklung (.NET) wird zunehmend der Monorepository-Ansatz (Monorepo) verwendet. Im Gegensatz zu Multi-Repositories, bei denen jedes Projekt in seinem eigenen Git-Repository lebt, speichert ein Monorepository den gesamten Code eines Unternehmens oder Produkts in einem zentralen Speicher. Für .NET-Entwickler bedeutet dies eine einzige Solution, gemeinsame Bibliotheken und eine vereinfachte CI/CD-Konfiguration. In diesem Artikel werden wir erläutern, wie man ein Monorepository mit C# richtig organisiert, Codebeispiele zeigen und die wichtigsten Vorteile diskutieren.
1. Vorteile eines Monorepositorys für .NET
Ein Monorepository ist besonders nützlich für Teams, die an mehreren verwandten .NET-Projekten arbeiten: Microservices, Webanwendungen, Klassenbibliotheken. Die Hauptvorteile sind:
- Einheitliche Abhängigkeitsversionen — alle Projekte verwenden dieselben Versionen von NuGet-Paketen, was Konflikte vermeidet.
- Vereinfachtes Refactoring — Änderungen an einer gemeinsamen Schnittstelle oder einem Datenmodell werden sofort auf alle Konsumenten angewendet.
- Gemeinsame Git-Historie — atomare Commits, die mehrere Projekte betreffen, sind an einem Ort sichtbar.
- Zentralisierte CI/CD — eine einzige Pipeline für Build, Test und Deployment aller Komponenten.
Für C# wird ein Monorepository um eine einzige .sln-Datei (Solution) herum aufgebaut, die auf alle Projekte verweist. Dies ermöglicht die Nutzung der integrierten Tools von Visual Studio und der .NET CLI zur Verwaltung von Abhängigkeiten.
2. Struktur eines Monorepositorys für C#
Betrachten wir eine typische Struktur eines Monorepositorys für eine .NET-Solution. Sie könnte so aussehen:
MyCompany/├── src/│ ├── MyCompany.Common/ # Gemeinsame Bibliothek│ │ ├── MyCompany.Common.csproj│ │ └── ...│ ├── MyCompany.WebApi/ # Web-API│ │ ├── MyCompany.WebApi.csproj│ │ └── ...│ └── MyCompany.BackgroundJob/ # Hintergrunddienst│ ├── MyCompany.BackgroundJob.csproj│ └── ...├── tests/│ ├── MyCompany.Common.Tests/│ ├── MyCompany.WebApi.Tests/│ └── MyCompany.BackgroundJob.Tests/├── docs/ # Dokumentation├── scripts/ # Skripte für CI/CD├── .gitignore└── MyCompany.sln # Einheitliche SolutionSchlüsselelemente dieser Struktur:
- src/ — Ordner mit dem Quellcode. Jedes Projekt ist ein eigener Ordner mit einer eigenen .csproj-Datei.
- tests/ — Ordner mit Tests. Die Namen der Testprojekte wiederholen die Namen der Hauptprojekte mit dem Suffix .Tests.
- docs/ — Dokumentation (README, Architekturentscheidungen).
- scripts/ — Skripte zur Automatisierung von Build oder Deployment.
- MyCompany.sln — Einheitliche Solution-Datei, die alle Projekte enthält.
Eine solche Struktur vereinfacht die Navigation und ermöglicht das einfache Hinzufügen neuer Projekte ohne Änderung der Stammkonfiguration.
3. Einrichtung einer einheitlichen Solution und gemeinsamer Abhängigkeiten
Verwenden Sie zum Erstellen eines Monorepositorys in .NET den Befehl dotnet new sln und fügen Sie dann Projekte hinzu:
# Stammordner erstellen und dorthin wechselnmkdir MyCompany && cd MyCompany
# Leere Solution-Datei erstellendotnet new sln -n MyCompany
# Ordnerstruktur erstellenmkdir src tests docs scripts
# Projekte erstellendotnet new classlib -n MyCompany.Common -o src/MyCompany.Commondotnet new webapi -n MyCompany.WebApi -o src/MyCompany.WebApidotnet new console -n MyCompany.BackgroundJob -o src/MyCompany.BackgroundJob
# Projekte zur Solution hinzufügendotnet sln add src/MyCompany.Common/MyCompany.Common.csprojdotnet sln add src/MyCompany.WebApi/MyCompany.WebApi.csprojdotnet sln add src/MyCompany.BackgroundJob/MyCompany.BackgroundJob.csprojFügen wir nun einen Verweis auf die gemeinsame Bibliothek aus der Web-API hinzu: