Features weiterliefern, während jemand das Fundament saniert

Sandor Farkas
Gründer & Lead Developer
Experte für Softwareentwicklung und Legacy-Code-Optimierung
LinkedInDer übliche Einwand gegen die Reparatur einer alten Codebasis ist nicht, dass die Arbeit zu schwer ist. Es ist, dass das Geschäft nicht lange genug stillstehen kann, damit jemand sie erledigen kann. Der Vertrieb hat ein Feature für das nächste Quartal versprochen, der Vorstand will sehen, dass die Roadmap eingehalten wird, und niemand will derjenige sein, der einem Kunden sagt, dass das Team sechs Monate ohne neue Releases braucht. Legacy-Modernisierung ohne Feature-Freeze ist das, was die meisten Teams ohnehin am Ende tun - nicht weil es ein Kompromiss ist, sondern weil es die einzige Version der Modernisierung ist, die überhaupt genehmigt wird.
Das ist eine gute Nachricht, denn ein kompletter Stopp ist selten das, was die Codebasis ohnehin braucht. Die meisten Systeme, die über Jahre Workarounds angesammelt haben, brauchen keinen Neuanfang auf der grünen Wiese. Sie brauchen ein stetiges, sichtbares Reparaturprogramm, das parallel zur normalen Lieferung läuft, mit einem eigenen Stundenbudget und einer eigenen Methode, um zu belegen, dass es funktioniert.
Warum ein Freeze von Anfang an die falsche Forderung ist
Ein Feature-Freeze verlangt zwei Dinge, die sich aus derselben Entscheidung nur schwer gewinnen lassen: Zeit und das Vertrauen, dass diese Zeit gut genutzt wird. Führungskräfte, die einen Freeze genehmigen, setzen Monate verlorener Marktposition auf einen Plan, den sie meist erst nach dessen Abschluss überprüfen können. Diese Wette geht oft genug schief, dass die meisten erfahrenen Teams aufhören, sie vorzuschlagen.
Es gibt auch einen technischen Grund, warum ein Freeze weniger hilft, als es klingt. Das Risiko eines Legacy-Systems sitzt nicht an einer einzigen Stelle, die man in einer ruhigen Phase auf einen Schlag aufräumen könnte. Es verteilt sich über Dutzende Dateien, eine Handvoll fragiler Integrationen und ein Datenbankschema, das niemand mehr angefasst hat, seit die Person, die es verstanden hat, das Unternehmen verlassen hat. Das Einstellen der Feature-Arbeit macht diese Liste nicht kürzer. Es nimmt nur den Druck weg, der ein Team normalerweise zur Priorisierung zwingt - weshalb sich ein Freeze monatelang hinziehen kann, ohne ein klares Ende zu haben.
Die Alternative besteht darin, Modernisierung als laufende Wartung mit einem festen Anspruch auf den Kalender zu behandeln - genau so, wie eine Fabrik die Wartung ihrer Maschinen um die Produktion herum plant, statt die Linie für einen Monat stillzulegen. Symfony-Anwendungen, die von Version 5 auf 7 migrieren, sind ein direktes Beispiel: Die Deprecation-Bereinigung und der Framework-Sprung passieren beide, während das Team weiter Releases liefert, weil die Arbeit in Stücke zerlegt wird, die klein genug sind, um innerhalb eines normalen Sprints abgeschlossen zu werden.
Legacy-Modernisierung ohne Feature-Freeze beginnt mit einem festen Stundenanteil
Die eine Veränderung, die den größten Unterschied macht, ist auch die am einfachsten zu erklärende für einen fachfremden Entscheider: Legt fest, welcher Prozentsatz der Engineering-Stunden in die Grundlagenarbeit fließt, schreibt ihn in den Sprint-Plan und behandelt ihn als nicht verhandelbar - statt als etwas, das nur passiert, wenn noch Zeit übrig ist.
Eine gängige Aufteilung für ein Team mit echten technischen Schulden liegt zwischen zwanzig und dreißig Prozent der Stunden. Das reicht aus, um innerhalb eines Quartals stetigen Fortschritt zu sehen, ohne die Feature-Roadmap auszuhungern, auf die das Geschäft zählt. Die genaue Zahl ist weniger wichtig als die Gewohnheit, sie zu schützen. Sobald die Aufräumzeit zu dem Posten wird, der gestrichen wird, wann immer eine Deadline enger wird, hört die Schuld auf zu sinken, und das nächste Freeze-Gespräch beginnt wieder bei null.
Wonach sollte ein fachfremder Entscheider hier fragen? Eine kurze, klare Liste pro Sprint, was die Aufräumstunden gebracht haben: eine aktualisierte Abhängigkeit, ein Modul mit neuer Testabdeckung, eine gefährliche Abkürzung, die entfernt wurde. Kann diese Liste nicht vorgelegt werden, werden die Stunden wahrscheinlich wieder in die Feature-Arbeit gesaugt, und die Aufteilung existiert nur auf dem Papier.
Feature-Flags machen riskante Änderungen umkehrbar
Feature-Flags erlauben es einem Team, neuen oder umgeschriebenen Code in Produktion zu bringen, bevor ihm vollständig vertraut wird, und ihn dann für einen kleinen Teil des Traffics zu aktivieren, um zu beobachten, was passiert. Geht etwas schief, besteht die Lösung darin, einen Schalter umzulegen, statt ein Deployment zurückzurollen und einem Kunden einen Ausfall erklären zu müssen.
Das spielt für die Modernisierung speziell deshalb eine Rolle, weil der riskanteste Moment jeder Legacy-Bereinigung der Cutover ist - der Punkt, an dem der Traffic vom alten Code-Pfad auf den neuen wechselt. Flags lassen diesen Cutover schrittweise und unauffällig geschehen: zehn Prozent der Anfragen diese Woche, fünfzig Prozent nächste Woche, alle, sobald das Team gesehen hat, dass es unter echter Last stabil bleibt. Ein fachfremder Stakeholder muss nicht verstehen, wie das Flag funktioniert. Er muss wissen, dass das Team eine Möglichkeit hat, eine schlechte Änderung innerhalb von Minuten statt Stunden zurückzunehmen - und das ist der Grund, warum Releases während eines Modernisierungs-Vorstoßes in der Regel weniger ereignisreich sind als die, die ohne jedes Sicherheitsnetz passieren.
Das System Stück für Stück verschieben, statt alles auf einmal
Der Strangler-Ansatz, benannt nach einer Feigenart, die um einen Wirtsbaum herum wächst, bis sie ihn schließlich ersetzt, ist das Muster hinter den meisten erfolgreichen Legacy-Migrationen, die ohne Freeze stattgefunden haben. Neuer Code wird neben dem alten System aufgebaut statt an dessen Stelle, und der Traffic wird jeweils ein Feature oder ein Modul nach dem anderen auf das neue Stück umgeleitet. Das alte System läuft weiter für die Teile, die noch niemand angefasst hat - bis es nichts mehr zu tun hat. Die Mechanik dahinter haben wir ausführlicher in unserem Beitrag zum Strangler-Fig-Pattern behandelt, einschließlich der Frage, wie man das erste zu verschiebende Stück auswählt.
Der geschäftliche Nutzen dieses Ansatzes ist auch ohne die technischen Details leicht nachvollziehbar. Ein Rewrite verlangt von dir, darauf zu vertrauen, dass ein brandneues System, das nur im Labor getestet wurde, am Tag des Go-Live alles bewältigt, was das alte bewältigt. Eine Strangler-Migration verlangt von dir, etwas viel Kleinerem zu vertrauen: dass dieses eine Modul, das diese Woche an eine Handvoll Nutzer ausgerollt wird, funktioniert. Jedes verschobene Stück ist eine Entscheidung, die du rückgängig machen kannst - keine Wette, die du einmal eingehst und für achtzehn Monate aushältst.
Was du messen solltest, um zu wissen, dass es wirklich funktioniert
Drei Kennzahlen sagen einem fachfremden Entscheider, ob eine Modernisierung, die parallel zur normalen Lieferung läuft, auf Kurs ist. Die erste ist, ob die Feature-Lieferung ungefähr stabil geblieben ist, denn ein Programm, das sich heimlich doch in einen Freeze verwandelt, hat seine eine Aufgabe verfehlt. Die zweite ist, ob die Liste der behobenen Punkte pro Sprint konkret statt vage ist, weil sich konkrete Punkte gegen das Versprochene prüfen lassen. Die dritte ist, wie oft ein Release in diesem Zeitraum ein Notfall-Rollback brauchte, denn eine sinkende Zahl ist hier das klarste Zeichen dafür, dass Flags und schrittweise Cutovers ihre Aufgabe erfüllen.
Keine dieser Zahlen erfordert das Lesen von Code. Sie erfordern, dass man konsequent danach fragt, Sprint für Sprint, und darauf achtet, wann die Antworten vager werden. Ein Modernisierungsplan, der diese Antworten nach einem Monat nicht liefern kann, scheitert nicht unbedingt - aber er beweist noch nicht, dass er funktioniert, und dieser Unterschied lohnt sich, vor Quartalsende nachzuhaken.
Ein Legacy-System braucht nicht, dass das Geschäft die Luft anhält, während es repariert wird. Es braucht einen festen Anteil an Aufmerksamkeit, ein Sicherheitsnetz für die riskanten Momente und einen Plan, Stück für Stück zu verschieben, statt alles auf einen einzigen Cutover-Termin zu setzen. Wenn dein Team ein System trägt, dem niemand mehr vollständig vertraut, und du einen Plan willst, der dich nicht zum Stoppen der Lieferung zwingt, schreib uns an hello@wolf-tech.io oder schau dir unsere Legacy-Code-Optimierung auf wolf-tech.io an. Wir sagen dir ehrlich, wie eine realistische Stundenaufteilung für deine Situation aussieht - keine generische Zahl, die aus der Codebasis irgendeines anderen übernommen wurde.
