Effektives Arbeiten mit Legacy Code. Refactoring und Testen bestehender Software

von Michael C. Feathers

Dass Tests wichtig sind, und dass Test-Driven-Development zu gut getesteter, gut strukturierter Software führt, weiß heutzutage jeder Programmierer. Leider war das nicht immer der Fall. Und so stehen wir oft vor der Herausforderung, ein System ohne Tests – ein also ein “Legacy System” nach Michael Feathers Definition – weiterzuentwickeln.

Doch wie gehen wir vor, wenn wir keine Testabdeckung haben, um sicherzustellen, dass unsere Änderungen nichts kaputt machen? Und wenn wir andererseits diese Tests nicht schreiben können, weil der Code zu komplex ist, viel zu viele Abhängigkeiten enthält und Logik und Präsentation miteinander verwoben sind?

Was können wir tun, wenn wir die zu testende Klasse nicht instanziieren können, weil wir ihrem Konstruktor ein Objekt übergeben müssen, das wir nicht einfach erzeugen können? Oder wenn die zu testende Methode auf die Datenbank zugreift – obwohl dieser Datenbankzugriff für die Funktionalität, die wir testen wollen, nicht notwendig ist?

Dieses Buch enthält einen Katalog von Mechanismen, um diese Abhängigkeiten zu lokalisieren und aufzubrechen. Und um den Code entsprechend zu modularisieren, wobei Modulgrenzen geschaffen werden – sogenannte “Seams” (deutsch: “Nähte”), an denen wir mit unseren Unit-Tests ansetzen können.

Die vorgestellten Strategien erlauben Änderungen mit minimalen Risiken. Die Refactoring-Features moderner IDEs erlauben es viele dieser Änderungen vollautomatisch durchzuführen. Änderungen, die es dann erlauben erste Tests zu implementieren, um darauf aufbauend weitreichendere Refactorings durchzuführen, die letztendlich die Codebasis in ein besseres Design überführen.

Der Autor erklärt alle Strategien anhand hervorragender, praxisnaher Beispiele, die hauptsächlich in Java und C++ geschrieben sind.

Leider wurde das Buch seit 15 Jahren nicht aktualisiert. Vor allem unerfahrene Programmierer sollten darauf achten, nicht jede Strategie dogmatisch umzusetzen. Für einige Mechanismen gibt es heutzutage bessere Alternativen; einige der Praktiken führen zu schlechterem, statt zu besserem Code; und das Thema Threadsicherheit – ein Kernthema in den meisten heutigen Unternehmensanwendungen – wird völlig außer Acht gelassen.

Beispielsweise braucht man heutzutage nicht mehr für jede zu mockende Klasse ein Interface. Mockito kann problemlos Klassen mocken, also Abhängigkeiten auflösen ohne ein Interface zu extrahieren. Und wer doch ein Interface extrahiert, beachte dabei bitte das Interface Segregation Principle! Die Aussage des Autors, "it's nice to have an interface that covers all of the public methods of a class" (S. 366), steht leider in krassem Widerspruch dazu.

Den Aufruf abstrakter Methoden aus einem Konstruktor heraus ("Extract and override factory method") sollte man besser vermeiden, wenn man nicht plötzlich einem nur teilweise initialisierten Objekt gegenüberstehen möchte. Aus gutem Grund verbietet C++ diese Praktik. Fünfundfünfzig Seiten nach der Einführung dieser Strategie rät der Autor schließlich vor deren Einsatz auch in Java ab.

Multithreading ist in fast keinem der älteren Klassiker ein Thema. Heutzutage kommt kein Programmierer mehr daran vorbei. Wenn du eine Klasse mit Strategien wie "Break Out Method Object" extrahierst, solltest du daher unbedingt einen Hinweis anbringen, dass die Klasse nicht threadsicher ist. (Alternativ kannst du Instanzvariablen durch geeignete Lock-Mechanismen schützen.)

Trotz der genannten altersbedingten Schwächen kann ich das Buch jedem Programmierer empfehlen, der mit Legacy-Code arbeiten muss. Erfahrene Programmierer haben sicherlich die eine oder andere Strategie schon einmal intuitiv angewendet. Andere Techniken mögen neu sein. So oder so, die Formalisierung hilft, die Strategien zu festigen, und ihre Namen verbessern die Kommunikation im Team.

Behalte nur zwei Dinge im Hinterkopf: Das Buch ist 15 Jahre alt, und für jede Regel gibt es eine Ausnahme!

🎧 Geeignet als Hörbuch? Nein, aufgrund zahlreicher Codebeispiele.

Andere Empfehlungen aus den Genres dieses Buches

* Hinweis: Wir teilen gerne unsere Lieblingsbücher mit dir! Als Amazon-Partner verdienen wir eine kleine Provision bei Einkäufen, die du über unsere Links tätigst. Dies hilft uns, weiterhin Inhalte zu erstellen, die dir gefallen.