Der Rewrite-Reflex

Warum neu schreiben wieder Legacy produziert

Der erste Impuls

Wer zum ersten Mal in eine gewachsene Codebasis eintaucht – unbekannte Strukturen, kryptische Bezeichner, Abhängigkeiten, die sich wie ein Geflecht durch das System ziehen – kennt den Impuls: neu schreiben. Sauber. Modern. Diesmal richtig.

Dieser Reflex ist verständlich. Er ist menschlich. Und er ist einer der teuersten Fehler, den ein Entwicklungsteam machen kann.


Was ist Legacy-Code überhaupt?

Bevor man über Rewrite oder Modernisierung spricht, lohnt sich ein Blick auf die Frage: Was ist Legacy-Code?

Die bekannteste Definition stammt von Michael Feathers:

„Legacy code is code without tests.“
(Working Effectively with Legacy Code, 2004)

Die Definition ist griffig und hat ihren Wert – sie macht das Problem messbar. Aber sie ist zu eng. Sie reduziert Legacy auf ein technisches Merkmal und blendet den eigentlichen Kern aus.

Eine treffendere Definition lautet: Code wird Legacy, wenn die Entscheidungen von gestern heute nicht mehr passen.

Das verschiebt die Perspektive grundlegend. Legacy ist kein Zustand des Codes – es ist ein Verhältnis zwischen Code und Kontext. Der Code war richtig: für die Anforderungen, das Wissen, die Werkzeuge und den Zeitdruck von damals. Legacy wird er, wenn sich der Kontext verschoben hat und der Code das nicht mitgemacht hat.

Folgerung: Code, den wir heute schreiben, kann morgen Legacy sein. Nicht weil wir schlechte Entscheidungen treffen, sondern weil sich der Kontext unweigerlich verschiebt.


Was ein Rewrite wirklich bedeutet

Joel Spolsky hat es 2000 auf den Punkt gebracht:

„It’s the single worst strategic mistake that any software company can make: to rewrite the code from scratch.“
(Things You Should Never Do, 2000)

Warum so kategorisch? Ein Rewrite wirft nicht nur Code weg – er wirft akkumuliertes implizites Wissen weg.

Jede seltsame Konstruktion in einer gewachsenen Codebasis hat eine Geschichte:

Der Code sieht chaotisch aus – aber er läuft, weil er jahrelang gegen die Realität gehärtet wurde.
Ein Rewrite beginnt bei null. Sauber, modern – ohne dieses Wissen.


Dieselben Kräfte wirken weiterhin

Der Rewrite-Reflex basiert auf einer stillen Annahme: dass die Probleme des alten Codes im Code selbst liegen. Das stimmt nur zum Teil.

Faktoren wie:

…sind Eigenschaften der Umgebung, nicht des Codes. Ein Rewrite ändert daran nichts. Dieselben Kräfte wirken auf den neuen Code vom ersten Tag an.

In fünf Jahren wird jemand den „modernen“ Code von heute mit denselben Augen betrachten.


„Modern“ ist ein temporärer Zustand

Software lebt. Anforderungen ändern sich. Frameworks evolvieren. Paradigmen wechseln. Was heute als sauber gilt, ist morgen überholt.

Beispiel Yii – das Framework hinter LimeSurvey:

Drei Generationen, drei verschiedene Produkte. Jede Generation war zum Zeitpunkt ihrer Entstehung modern. Die Migration von Version zu Version ist ein massives Unterfangen.

LimeSurvey bleibt auf Yii 1, nicht aus Faulheit, sondern weil ein Wechsel einem Rewrite des gesamten Systems gleichkäme. Dies ist ein konkreter Beweis für Spolskys Warnung.


Was würde ein LimeSurvey-Rewrite bedeuten?

LimeSurvey ist funktionsreich, produktiv im Einsatz, mit einer großen aktiven Community. Ein Rewrite hätte zwei Optionen:

  1. Ohne Backward-Compatibility:

    • Neues Produkt, bestehende Installationen, Themes, Plugins, Datenbankstrukturen brechen
    • Migration aufwendig, Community riskant
    • Effekt: keine Verbesserung, sondern ein komplett neues System
  2. Mit Backward-Compatibility:

    • Alte Eigenheiten reproduzieren (30 Fragetypen, Token-System, Plugin-System, Expression Manager, Mehrsprachigkeit, dynamisches Datenbankmodell)
    • Ergebnis: ähnlicher Code, ohne die Praxiserfahrung, neue Bugs inklusive

Das Dilemma: Ein Rewrite verspricht den sauberen Schnitt, liefert aber entweder ein neues Produkt oder den gleichen Code in neu.


Die Alternative: Verstehen statt ersetzen

Der nachhaltigere Weg ist selten der dramatischere. Er beginnt damit, den alten Code als Dokument zu betrachten – eine unvollständige, manchmal widersprüchliche, aber reale Aufzeichnung von Entscheidungen unter echten Bedingungen.

Schrittweise Entflechtung bewahrt Wissen und schafft Raum für Verbesserung:

Es gibt keinen „fertigen“ Tag wie bei einem Rewrite. Aber es funktioniert – weil es die Realität akzeptiert, statt sie zu ignorieren.


Fazit

Legacy-Code ist kein Versagen. Er ist der Beweis, dass Software überlebt hat – durch wechselnde Anforderungen, Teams und Kontexte.

Der Rewrite-Reflex ist der Wunsch nach einem sauberen Blatt Papier. Aber Software existiert nicht auf einem leeren Blatt. Sie existiert in einer Umgebung, die sich verändert – und der Code, den wir heute schreiben, wird denselben Kräften ausgesetzt sein wie der Code, den wir heute ersetzen wollen.

Die Frage ist nicht: neu schreiben oder nicht?
Die Frage ist: Was wissen wir, das im alten Code steckt – und wie bewahren wir es, während wir ihn verbessern?