Bei einem neuen Projekt auf der grünen Wiese kann und sollte man sich von vornherein auf eine geeignete Architektur festlegen und diese in entsprechende (Maven-)Module mit jeweils eigenen Abhängigkeiten gießen. Bei so manchem gewachsenen oder gewucherten Erbstück ist das nachträglich nicht mehr möglich. Die Struktur dieser Schätze gilt es zu erkennen und laufend zu verbessern. In diesem Artikel erfahren Sie, wie man das systematisch bewerkstelligt. Dafür kommt eine kleine Java-Bibliothek zum Einsatz, mit der man Abhängigkeiten zwischen Klassen prüfen kann.
Vorgeschichte
Anfang der 2000er Jahre hatte ich als Junior-Entwickler in einem klassischen EJB-2.0-Projekt die Aufgabe, (Unit-)Tests zu schreiben, um nachträglich irgendwie die Codequalität zu verbessern. Diese Aufgabe stellte sich als äußerst schwierig heraus, da alles miteinander verwoben war und man keine Teilfunktionalität testen konnte, ohne die ganze Anwendung hochzufahren. Die Anwendung lief eher schlecht als recht, es gab ständig irgendwelche Probleme, Fehler waren schwer nachzuvollziehen und vermeintliche Fehlerbehebungen führten zu neuen Problemen. Daher wurde ein externer Berater hinzugezogen. Dieser hatte zusammen mit dem Architekten die Struktur des Projekts herausgearbeitet und einen Lösungsweg aufgezeigt. Daraus ist ein umfangreiches Refactoring-Projekt entstanden, bei dem vor allem zyklische Abhängigkeiten aufgelöst wurden.
Zur Überwachung des Fortschritts wurde ein Open-Source-Tool mit dem Namen Dependometer eingesetzt [1]. Ich habe das Tool in Folgeprojekten verwendet, aber bald festgestellt, dass im stressigen Projektalltag niemand die Zeit hat, komplizierte HTML-Reports zu analysieren. Ideal wäre eine rote Ampel in der CI-Umgebung, die auf Architekturverletzungen hinweist, ähnlich einem fehlgeschlagenen Unittest. Es ist also nichts naheliegender, als solche Architekturprüfungen als Unittest umzusetzen. Geeignete Bibliotheken dafür waren allerdings Mangelware und brachten selbst wieder Abhängigkeitskonflikte mit sich. Ich habe mich deshalb entschlossen, selbst eine Bibliothek für diesen Zweck zu schreiben, die keinerlei Abhängigkeiten hat und sich mit einer sehr alten Java-Version (Java 6) begnügt, damit sie wirklich bei jedem Erbstück eingesetzt werden kann. Natürlich läuft die Bibliothek auch mit neueren Java-Versionen bis hin zu Java 16.