Die Wiederverwendbarkeit von Code durch gut strukturierte Klassenbibliotheken ist entscheidend für den Software-Entwicklungsprozess. Eine klare Dokumentation und durchdachte Architektur helfen, Spaghetti-Abhängigkeiten zu vermeiden und die Nutzung in Projekten zu vereinfachen
In vielen Projekten stellt sich die Frage, wie du Code, der auch anderswo nützlich sein kann, am besten wiederverwendest. Eine sinnvolle Strategie ist die Auslagerung von Funktionalitäten in Klassenbibliotheken. Die Gestaltung dieser Bibliotheken ist entscheidend: Funktionalitäten sollten so konzipiert sein, dass sie in unterschiedlichen Projekten eingesetzt werden können, während sie gleichzeitig konfigurierbar bleiben.
Strukturierung der Klassenbibliotheken
Ein erster Schritt ist, sich der Abhängigkeiten deiner Klassenbibliotheken bewusst zu werden. Optimalerweise sollte eine Bibliothek mit allgemeiner Funktionalität keine oder kaum Abhängigkeiten zu anderen Projekten oder Drittanbieter-Paketen aufweisen und nur das konsumieren, was es auch wirklich braucht. Meist sind zu viele Abhängigkeiten zu unterschiedlichen Paketen ein guter Indikator, dass man die Klassenbibliothek aufteilen sollte.
Gleichzeitig ist es wichtig, die spezifische Domäne zu berücksichtigen. Wenn z.B. POCO-Klassen oder auch Enums in allgemeinen Bibliotheken landen, die nur für einen Teil der Projekte relevant sind, sind sie hier nicht richtig aufgehoben.
Es empfiehlt sich, kleinere, gezielte Bibliotheken zu erstellen, ohne in zu viele winzige Bibliotheken zu zerfallen. Ein ausgewogener Mittelweg sollte im Team erarbeitet werden. So kannst du deine Bibliotheken auch nach technologischen Bereichen strukturieren, zum Beispiel für Web-APIs oder Automatisierte Tests.
Dies ermöglicht es jedem Projekt, nur die relevanten Shared Libraries zu verwenden, ohne unnötige Abhängigkeiten aufzubauen.
Vermeidung von Spaghetti-Abhängigkeiten
Spaghetti-Abhängigkeiten sind zu vermeiden. Eine klare Struktur legt fest, welche Anwendung von welcher Shared Library abhängt und wie die Hierarchien zwischen den Bibliotheken aussehen. Architekturtests oder Layer-Diagramme mit automatisierten Validierungsregeln sind hilfreiche Werkzeuge, um diese Beziehungen zu klären und verworrene Abhängigkeiten zu vermeiden.
Wenn euer Dependency Graph wie folgt aussieht, solltet ihr euch Gedanken über die Struktur eurer Bibliotheken machen:
Zum Thema Architekturtests kommen wir in einem späteren Artikel zurück.
Entscheidung zur Bereitstellung
Bei der Bereitstellung deiner Klassenbibliothek solltest du entscheiden, ob du sie direkt einbindest oder als Paket zur Verfügung stellst. Diese Entscheidung hängt von der Verwaltung deiner Projekte im Source Control und der Notwendigkeit zur Versionierung ab.
Eine sinnvolle Versionierung ist besonders relevant bei Breaking Changes. Wenn die Nutzung der Shared Library in anderen Projekten deines Unternehmens geplant ist, ist die Bereitstellung als NuGet-Paket empfehlenswert. So können Breaking Changes in der Bibliothek klar kommuniziert und die Projekte entsprechend angepasst werden.
Soll die Bibliothek nur in einem Mono-Repository verwendet werden, können Anpassungen bei Breaking Changes meist unkompliziert direkt in den betroffenen Anwendungen umgesetzt werden. Hierbei ist der Overhead, deine Bibliothek als NuGet-Paket bereitzustellen, meist nicht notwendig.
Bedeutung der Dokumentation und Kommunikation
Nicht zuletzt spielt die Dokumentation eine entscheidende Rolle. Selbst die beste Bibliothek ist wertlos, wenn die Mitarbeitenden nicht wissen, welche Funktionen sie bietet und wie diese zu nutzen sind.
Ausführliche Dokumentation, regelmäßige Schulungen und klare Kommunikation sind notwendig, um die Nutzung im Entwicklungsteam sicherzustellen. Dabei ist es besonders wichtig, dass die Informationen über gemeinsame Klassenbibliotheken auch an andere Entwickler:innen weitergegeben werden, damit sie wissen, dass es diese Bibliotheken gibt, wie sie genutzt werden sollten und was zusätzlich hinzugefügt werden darf.
XML-Kommentare z.B. sind besonders nützlich, da sie die Nutzung im Code-Editor unterstützen und die Generierung von Dokumentationen erleichtern. Vorausgesetzt sie beschreiben, was eine Funktion im Detail macht und wieso, statt eines autogenerierten Kommentars.
Ein Beispiel kannst du dem Open Space Planner entnehmen. Dieses ist auf eine komplexere Projektstruktur ausgelegt.
Wie und nach welchen Kriterien legst du Klassenbibliotheken in deinen Projekten an?
Schau gerne bei uns auf LinkedIn vorbei und diskutiere mit.
Florian ist Solution Architect und Microsoft Most Valuable Professional (MVP) für Azure & Azure IoT mit langjähriger Erfahrung im Bereich DevOps, Cloud und Digitalisierung. Er unterstützt Unternehmen dabei, effiziente und effektive Lösungen zu entwickeln, die ihre digitalen Projekte nachhaltig zum Erfolg führen.
Wenn Swagger UI an seine Grenzen stößt, ist Scalar eine überzeugende Alternative. Hier erfährst du, wie du es von der einfachen Einbindung in Swashbuckle bis zum automatisierten Push in die Scalar Registry aus der CI-Pipeline einsetzt.
Sensible Nutzerdaten haben in Logs nichts verloren. Dieser Artikel zeigt, wie du mit .NET Data Redaction und LogTape systematisch personenbezogene Daten maskierst, bevor sie in den Logs landen.
Lokale Entwicklung ist oft unnötig kompliziert. Hier erfährst du, wie du mit modernen Tools, automatisierter Konfiguration und klarer Struktur eine stabile Entwicklungsumgebung aufbaust, sodass du weniger Zeit mit Setup verbringst und dich mehr aufs Programmieren konzentrieren kannst.
Guter Code ist nicht nur funktional, sondern auch lesbar. Hier erfährst du, wie du Regeln definierst, Tools integrierst und Formatierung zum festen Bestandteil eures Entwicklungsprozesses machst.
Sensiblen Daten im .NET-Umfeld gehört besondere Aufmerksamkeit. Hardcoding vermeiden und sichere Speicherlösungen wie User Secrets, Azure Key Vault und die Data Protection API nutzen.
Die Verwendung der Directory.Build.props-Datei ermöglicht eine zentrale Konfiguration für .NET-Projekte, was die Verwaltung von Abhängigkeiten und Einstellungen vereinfacht. So kannst du sicherstellen, dass alle Projekte konsistent agieren und die aktuellen Standards befolgen.
Projektstandards starten oft als Kopie und driften danach auseinander. LunaPack macht daraus versionierte Packs mit nachvollziehbaren Updates, Ownership und einem kontrollierten Weg in bestehende Repositories.
Gute Prompts und Instructions reichen nicht. Erst eine belastbare Grundlage in der Softwareentwicklung aus Anforderungen, Tests, Pipelines und Betrieb macht Änderungen mit GenAI nutzbar.