Alptraum Legacy Code – Wie Profis damit umgehen

| Autor / Redakteur: Lars Jacobi * / Sebastian Gerstl

Vermeidung von Legacy Code: Das altbekannte Vier-Augen-Prinzip ist oft Schlüssel zum Erkennen und Bewerten von Problemen.
Vermeidung von Legacy Code: Das altbekannte Vier-Augen-Prinzip ist oft Schlüssel zum Erkennen und Bewerten von Problemen. (Bild: Matej Kastelic / Clipdealer)

Legacy Code bringt oft gewaltige Probleme bei der Entwicklung neuer Features mit: Variablen tragen nichtssagende Namen, Methoden sind zu überkomplexen Konstrukten mutiert und automatisierte Tests sind meist wenig bis gar nicht vorhanden. Wie geht man damit um?

Es ist ziemlich schwer, eine klare, akademische Definition für Legacy Code zu finden, da verschiedene Experten und Plattformen das Phänomen unterschiedlich definieren. Wikipedia definiert Legacy Code recht simpel als Code, der zu einer älteren Software-Version gehört oder von einem anderen Software-Entwickler geschrieben wurde. Techopedia definiert Legacy Code als Code in einer alten, nicht mehr unterstützten Programmiersprache oder Plattform. Michael C. Feathers, Autor des Buches „Working Effectively with Legacy Code“, definiert Legacy Code hingegen als „Code ohne Unit Tests“.

Für diesen Artikel wird der Einfachheit halber jeder Code als Legacy Code bezeichnet, der eines oder mehrere der folgenden Kriterien erfüllt:

  • Der Code ist nicht durch automatisierte Tests abgesichert.
  • Der Code entspricht nicht den aktuellen „Regeln der Kunst“ (Clean Code).
  • Die Entwickler scheuen sich, den Code zu verändern oder zu erweitern („Never touch a running system”).
  • Keiner versteht den Code mehr wirklich.

Entstehung und Konsequenzen von Legacy Code

Einen Satz wird man im Umfeld von Legacy Code nahezu immer zu hören bekommen: „Das ist historisch gewachsen …“ Legacy Code entsteht nicht über Nacht, sondern oft schleichend und über einen langen Zeitraum hinweg. Der Schlüsselaspekt hierbei ist die Häufigkeit der gewissenhaften Wartung des Codes: Eine Maschine muss gewartet werden – Programmcode bildet da keine Ausnahme. Leider wird dieser Fakt in der Regel für kurzfristige Gewinne und neue Projektziele immer wieder übergangen, in den Führungsetagen oft sogar komplett ausgeblendet.

Legacy Code entsteht allerdings nicht nur in den kontrollierenden Unternehmensebenen. Legacy Code wird auch durch Software-Entwickler begünstigt, die nicht am Ball geblieben sind, sich nicht weiterbilden, zu wenig Aufwand in das Testen ihres Codes stecken und an alten Standards festhalten. Und selbst disziplinierten Entwicklern fällt es zunehmend leichter, schlechten Code zu schreiben, wenn bereits schlechter Code in ihrem direkten Programmierumfeld existiert. Dieses Phänomen wird auch als „Broken-Window-Prinzip“ bezeichnet.

Schwerwiegende technische Folgen von Legacy Code verhärten sich zu unwartbarer, unerweiterbarer und untestbarer Software. Es dauert eine Ewigkeit ein neues Feature zu implementieren, Code zu dokumentieren oder einen kleinen Bug zu fixen. Dabei richtet Legacy Code nicht nur auf technischer Ebene, sondern auch im Team erhebliche Schäden an: Der Lieferdruck steigt, genauso wie der Frust über die Handlungsunfähigkeit. Die Projektkosten explodieren, die Aufwände sind nicht mehr akkurat schätzbar, die Probleme werden in sämtlichen Bereichen des Unternehmens spürbar und können dieses im schlimmsten Fall sogar in den Ruin treiben. Auch den Kunden ist aufgefallen, dass rund 30% Mehrkosten als On-Top-Budget längst eine feste kalkulatorische Größe für Software-Qualität darstellt.

Irrtümer zum richtigen Umgang mit Legacy Code

Wie aber geht man mit Legacy Code um? Soll man das existierende Projekt aufgeben, den Code verwerfen und neu schreiben? In den allermeisten Fällen ist die klare Antwort auf diese Frage: Nein! Das Problem Legacy Code lässt sich auch langfristig nicht effektiv lösen, indem man das Projekt neu aufsetzt. Man kann kein Produkt mit den aktuell vorhandenen personellen Ressourcen warten und parallel dazu ein neues Produkt entwickeln. Selbst wenn das Produkt noch nicht auf dem Markt ist und die Führungsriege die erforderlichen Mittel zum Reset freigibt, führt ein Neu-Aufsetzen des Projektes in der Regel unwiderruflich zu neuem Legacy Code.

Der Grund dafür ist die Mentalität der Entwickler. Viele Software-Entwickler halten an alten Vorgehensweisen und Techniken fest und sind gegenüber Veränderungen am Alt-Bewährten oft misstrauisch. „Same old thinking – same old result“ führt dazu, dass alte Probleme am Ende nur neu verpackt werden. Diese Betriebsblindheit bildet in einem neu-aufgesetzten Projekt den Nährboden für neuen Legacy Code.

Refactoring: der Anfang vom Ende des Legacy Codes

Will man dem wuchernden Legacy Code wirklich Herr werden, dann muss man investieren. Zu allererst muss das Personal geschult werden: Wie soll Quellcode nach den aktuellen Standards aussehen, geschrieben und getestet werden? Ab wann ist Code tatsächlich Clean Code?

Nach Martin folgt der Clean-Code-Ansatz, neben grundlegenden Regeln der Namensgebung und Struktur von Variablen und Methoden, fünf einfachen Prinzipien, die als SOLID-Prinzipien bekannt sind:

  • Single responsibility principle (SRP)
  • Open/closed principle (OCP)
  • Liskov substitution principle (LSP)
  • Interface segregation principle (ISP)
  • Dependency inversion principle (DIP)

Der Clean-Code-Ansatz ist hierbei keine einmalige Lektüre, sondern eine Mentalität, die gelebt und ständig erneuert werden muss. Es wird ein Gefühl für Ästhetik entwickelt, das dazu motiviert, „schönen“ Code zu schreiben, der lesbar und wartbar ist. Software-Entwickler, die den Clean-Code-Ansatz verinnerlicht haben, sehen in ihrem Code nicht nur Funktionalität, sondern, ähnlich wie ein Poet ein Gedicht verfasst, auch Kunst. Das Ergebnis ist dabei nicht nur der Code, sondern auch das Erfolgserlebnis des Entwicklers und eine Art von Stolz, die den Blick für „unsauberen“ Code schärft.

Ist das erst in den Köpfen und Herzen der Entwickler angekommen, muss Zeit für die Qualitätssicherung der Anwendung eingeplant und freigegeben werden. Software-Qualität entsteht durch Refactoring von Quellcode. Refactoring ist eine Technik zum Restrukturieren von Quellcode, ohne das Verhalten des Codes zu verändern. Vor allem Refactoring im Team bietet hervorragende Möglichkeiten mit Methodiken, wie etwa Pair Programming, die Qualität der Software zu verbessern. Gleichzeitig tauschen die Teammitglieder so auch Wissen und Know-how aus.

Professionelles Refactoring von Legacy Code verfolgt einen testgetriebenen Entwicklungsansatz (Test Driven Development, TDD). Diese durch einen Test-First-Ansatz charakterisierte Methodik sieht vor, dass Code, der geändert oder hinzugefügt werden soll, zuvor durch automatisierte Tests abgedeckt ist. Diese Tests sollten in Form von Unit Tests oder Integration Tests vorliegen und müssen bezogen auf Legacy Code keinerlei fachlichen Anforderungen entsprechen, sondern das tatsächliche Verhalten der Anwendung sichern! In nahezu jedem Legacy-System ist zunächst wichtiger, was das System tut, als das, was es tun soll. Feathers definiert diese Tests in seinem Buch „Working Effectively with Legacy Code“ als Characterization Tests [2].

Ist ein solides Sicherheitsnetz erst einmal gespannt, kann man sich mit den eigentlichen Änderungen im Legacy Code befassen. Hier gilt die Devise zunächst kleine Änderungen vorzunehmen und dann über die Tests die bisherige Funktionalität des Codes sicherzustellen: Ändern -> Testen -> Ändern -> Testen

Feathers bezeichnet diese Methode als „Cover and Modify“. Sie stellt eine sehr solide Vorgehensweise dar, um Legacy Code Stück für Stück verständlicher und wartbarer zu machen. Dafür müssen jedoch unbedingt sogenannte charakteristische Tests vorhanden sein. Schreiben Sie keine Tests, verfolgen Sie einen Ansatz, der von Feathers als „Edit and Pray“ bezeichnet wird: Sie planen Ihre Änderungen und hoffen nach dem Check-in, dass Sie nichts kaputt gemacht haben. Dieses Vorgehen sollten Sie verständlicherweise vermeiden.

Effektiver Schutz vor Legacy Code

An diesem Punkt stellt sich die Frage: Wie schützt man das Produkt vor Legacy Code? Martin hat hierzu eine simple Regel aufgestellt, die sogenannte „Boy Scout Rule“: „Leave the code cleaner than you found it! It’s not enough to write code well, the code has to be kept clean over time.“

Im Kern wirbt die Boy Scout Rule um ein simples Verhalten: Lassen Sie den Code sauberer zurück, als Sie ihn vorgefunden haben. Es ist eben nicht genug, sauberen Code zu schreiben, man muss ihn auch über einen längeren Zeitraum hinweg pflegen. In Zeiten, in denen Software durch neue Anforderungen stetig wächst, hat die Wartung besonderes Gewicht. Wenn sich jeder Entwickler an diese simple Regel hält, wird Legacy Code nicht nur aktiv vermieden, auch die Code-Qualität wird langsam aber stetig verbessert.

Eine solide Testabdeckung ist für Software-Projekte essentiell. Ein Projektteam kann und muss sich effektiv gegen Legacy Code schützen, indem es jedes neu implementierte Feature durch automatisierte Tests absichert. Auch Code Reviews tragen durch ihr Vier-Augen-Prinzip erheblich zur Prävention bei. Diese Methodik gilt in vielen Software-Projekten sogar als das Quality Gate schlechthin.

Legacy Code ist der flüssige Teer in der Natur eines jeden Software-Projektes. Er führt dazu, dass die Entwicklung immer langsamer, Änderungen immer riskanter und die Teammitglieder immer frustrierter werden. Im schlimmsten Fall führt Legacy Code zum Ruin eines Unternehmens. Das Säubern von Legacy Code zu Clean Code ist mit viel Arbeit verbunden. Aber eines ist klar: Es ist ein notwendiges Übel. Hat man diesen Weg einmal eingeschlagen, dann lohnt er sich. Die Software-Qualität steigt, die Kunden sind zufriedener und die Entwicklungsteams können effektiv arbeiten.

* Lars Jacobi ist Softwareentwickler bei Method Park in Erlangen.

Kommentar zu diesem Artikel abgeben

Schreiben Sie uns hier Ihre Meinung ...
(nicht registrierter User)

Zur Wahrung unserer Interessen speichern wir zusätzlich zu den o.g. Informationen die IP-Adresse. Dies dient ausschließlich dem Zweck, dass Sie als Urheber des Kommentars identifiziert werden können. Rechtliche Grundlage ist die Wahrung berechtigter Interessen gem. Art 6 Abs 1 lit. f) DSGVO.
Kommentar abschicken
copyright

Dieser Beitrag ist urheberrechtlich geschützt. Sie wollen ihn für Ihre Zwecke verwenden? Kontaktieren Sie uns über: support.vogel.de/ (ID: 45686014 / Tools & Softwarekomponenten)