Big-Bang-Modernisierung – ein Erfahrungsbericht

Will man alten Code modernisieren, stehen viele Möglichkeiten zur Auswahl. Kontinuierlich Teile des Alt-Codes durch neue Module ersetzten, entlang eines Features einen Durchstich durch die Software aktualisieren, und so weiter. Von einer Methode wird jedoch häufig abgeraten: Die sogenannte Big Bang Modernisierung – also ein kompletter Rewrite.

Dabei wird der alte Code nicht mehr angefasst und die gesamte Anwendung von Grund auf neu geschrieben. Diese Methode wird eher in kleinen Projekten eingesetzt, in denen das Feature-Set überschaubar ist.

Ich möchte nun gerne über meine Erfahrungen mit einer Big-Bang-Modernisierung in einem Projekt berichten, bei dem das nicht der Fall war.

Und gleich zu Beginn noch ein Spoiler: Entgegen der Wahrscheinlichkeit war die Modernisierung erfolgreich und die neue Anwendung läuft produktiv.

Warum will man eine Big-Bang-Modernisierung machen?

Die Big-Bang-Modernisierung hat offensichtliche Nachteile: Man kann in der Zeit keine neuen Features in die Alt-Anwendung einbauen (höchstens echte Bug-Fixes oder Sicherheitsupdates). Und man kann die modernisierte Version erst produktiv nehmen, wenn sie fertig ist – was ein hohes zeitliches und finanzielles Investment voraussetzt. 

Wir haben deshalb zuerst geprüft, ob eine Teil- oder „Stück-für-Stück“-Modernisierung durchführbar ist. Als klar wurde, dass die Code-Basis das nicht zuließ, haben wir uns für die Big-Bang-Lösung entschieden. 

Die zu modernisierende Anwendung baute auf einem Formular-Plugin in einem Content Management System auf. Diese Formulare diktierten den Aufbau der Datenbank und wurden zur Dateneingabe genutzt. Das User Interface, welches die Daten darstellte und Nutzer-Interaktionen verarbeitete, war von diesem CMS komplett unabhängig. Es bestand aus einem HTML-Gerüst, das mit jQuery-Selektoren manipuliert wurde. Die Daten wurden in PHP per SQL direkt aus der Datenbank geholt.

Der Hauptgrund für die Modernisierung war, dass die Entwicklung neuer Features im User Interface immer zeitintensiver wurde. Aufgrund der Komplexität des JavaScript-Codes konnten Seiteneffekte nicht vorhergesehen werden und Bug-Fixes waren bei jedem neuen Feature nötig.

Bugs die im bestehenden Code entdeckt wurden, waren aufgrund der Seiteneffekte nur mit viel Zeitaufwand zu beheben. Weiterhin erhöhte jedes weitere Feature die ohnehin schon unangenehmen Ladezeiten.

Um die Wartbarkeit der Anwendung wiederherzustellen und die User Experience zu verbessern, musste modernisiert werden. Und Big Bang war demzufolge der einzig gangbare Weg.

Wie wir an die Modernisierung herangegangen sind

Schnell war klar, dass wir die Datenbankstruktur anpassen mussten. Das hatte zwei positive Effekte: Die bisherige Datenbank wurde durch das CMS und sein Formular-Plugin definiert. Passte man die Datenbank an, mussten diese beiden Abhängigkeiten aus dem Projekt entfernt werden; somit mussten diese Komponenten nach der Modernisierung auch nicht mehr gepflegt werden. Trotzdem wollten wir auf den realen Daten weiterarbeiten, weswegen wir eine Schicht aus SQL-Views zwischen die alte Datenbank und die neue Anwendung zogen. Das ermöglichte einen Parallelbetrieb von alter und neuer Anwendung und wir konnten die neue Datenbankstruktur Stück für Stück in den Views aufbauen. Dadurch blieb die Vergleichbarkeit von alter und neuer Anwendung erhalten.

Umstellungen im Backend

Eine weitere frühe Entscheidung war, Symfony als PHP-Framework einzusetzen. Anstatt direkt mit SQL auf die Datenbank zuzugreifen, konnten wir so Doctrine als ORM nutzen.

Stück für Stück haben wir in der alten Datenbank Entities identifiziert und entsprechende Views angelegt, die die benötigten Daten beinhalten. So konnten wir sparsam Informationen in die neue Datenbankstruktur ziehen. Stellte sich später heraus, dass wir zu wenige Daten mitgenommen haben, konnten wir die Views und Entities problemlos anpassen.

Auf diese Weise sind wir sichergegangen, dass wir keine „historischen“ Tabellenspalten in die neue Datenbank umziehen, die so gar nicht mehr gebraucht wurden.

… und im Frontend

Das User Interface sollte weiterhin in JavaScript entwickelt werden. Hier fiel die Entscheidung auf ES6, damit wir den Code objektorientiert aufbauen konnten. Später haben wir die Codebasis großteilig auf TypeScript umgestellt, da das sehr wenig Aufwand darstellte aber Typisierungs-Bugs ausschloss.

Die Formulare für die Content-Pflege, die bisher über ein Plugin des CMS erstellt wurden, bauten wir in React und Redux. Das brachte uns den Vorteil von wiederverwendbaren, generalisierten Komponenten, was wiederum leichter zu pflegen war. 

Administrative Aufgaben, wie etwa die Nutzerverwaltung, die bisher vom CMS gelöst wurden, ließen sich häufig durch existierende und gut gepflegte Symfony-Bundles ersetzen.

Modernisierung in Etappen

Wir haben die Modernisierung deswegen grob in Etappen oder Meilensteine aufgeteilt: 

  1. User Interface (und dementsprechende Entities) erstellen
  2. Export: Diese Funktion der Applikation musste neu geschrieben werden; die eingesetzten Technologien (PHPWord) haben sich jedoch nicht geändert
  3. Content-Verwaltung
  4. Administrative Bereiche und statische Seiten

Diese Meilensteine hatten allerdings teilweise fließende Übergänge, sodass beispielsweise Erkenntnisse aus Etappe Zwei durchaus zu Änderungen an Code aus Etappe Eins führen konnten.

Ab dem Zeitpunkt, an dem die administrativen Bereiche und die Content-Verwaltung im neuen System vorhanden waren, konnten wir die alte Datenbank durch die neue – die ja bisher nur in Views existiert hat – ersetzen. Um sicherzugehen, dass nach diesem Schritt keine Daten aus der alten Datenbank mehr fehlen, haben wir diese Meilensteine ans Ende gelegt. So hatte unser Kunde die Möglichkeit, das User Interface und den Export schon ausreichend zu testen und abzunehmen, und wir konnten uns sicher sein, dass keine „Hidden Features“ mehr fehlten.

Herausforderungen in der Modernisierung

Eine Schwierigkeit gleich vorweg: Unser Entwicklungs-Team hat neben dem Modernisierungsprojekt noch ein weiteres Projekt für den Kunden betreut. Diesen Scope-Wechsel sollte man während eines Modernisierungsprozesses vermeiden. Unabhängig davon stellen „Hidden Features“ wohl in den meisten Applikation die größte Herausforderung dar.

Der Umfang der Big-Bang-Modernisierung wird letztendlich durch die Alt-Anwendung definiert. Durch unseren Parallelbetrieb der Applikation konnten wir also immer wieder vergleichen, ob unser neues System das gleiche Verhalten zeigt wie das alte.

Wären da nicht die Sonderfälle …

Der Kunde oder wir stießen immer wieder auf versteckte Sonderfälle, die im normalen Betrieb der Anwendung nicht sichtbar wurden. Hier galt es nachzuforschen, wie dieser oder jener Sonderfall im alten Code gelöst wurden. Außerdem war das Fachwissen des Kunden gefragt: Kann man aus diesem Sonderfall eine Regel ableiten, die allgemein gültig im neuen System umgesetzt werden kann?

Kaum eine Anwendung ist bis ins letzte Verhalten vollständig dokumentiert – auch bei unserer war das nicht der Fall. Glücklicherweise konnten wir konstant mit dem Kunden Rücksprache halten. So konnten wir immer erforschen, ob ein Verhalten im alten System gewollt war und worin es begründet lag. Ohne diesen Kundenkontakt wären viele der „Hidden Features“ vermutlich unentdeckt geblieben.

Neu für alt

Im Lauf der Modernisierung hat sich ergeben, dass neue Features nötig waren, um das alte Verhalten in einem sinnvollen Weg abbilden zu können. Zum Beispiel gab es einige Sonderfälle, die fest im Code vergraben waren. Es war aus Entwicklersicht besser, es so zu implementieren, dass Sonderfälle vom Nutzer gepflegt werden können. Diese zusätzlichen Features sind zu Beginn der Modernisierung allerdings kaum vorherzusehen.

Folgerichtig wurde ein weiterer Umstand durch diese neuen sowie die „Hidden Features“ verschlimmert: Aufwände für die Umsetzung der Modernisierung zu schätzen.

Herausforderungen Aufwandsschätzung

Zu Beginn konnte weder der Kunde noch wir den kompletten Feature-Aufwand abschätzen. Und auch wenn wir uns schon frühzeitig auf einen Tech-Stack geeinigt hatten, mussten diese Entscheidung trotzdem in einzelnen Meilensteinen noch einmal genauer evaluiert und in Frage gestellt werden. Ist React für die Content-Verwaltung wirklich besser geeignet als beispielsweise Angular oder Vue? Ist PHPWord für den Word-Export wirklich die beste Lösung? Und wenn wir PHPWord einsetzen: Welcher Weg zum Erstellen von Word Dokumenten ist dann der sinnvollste?

All diese Entscheidungen machen eine Abschätzung natürlich schwierig. In unserer Modernisierung starteten wir deswegen zunächst in eine Mockup-Phase. Darin setzten wir das Symfony-Framework auf und erstellten mit Bootstrap und ES6 eine erste (wenig funktionale) Version des User Interfaces. Anhand der Erfahrungen der ersten paar Wochen konnten wir dann grob den zeitlichen Aufwand für die einzelnen Meilensteine in Vollzeit-Arbeitswochen schätzen.

Die Gesamtschätzung machte allerdings einen einen sehr großen Korridor zwischen Best- und Worst Case auf. Nach Abschluss von Etappe zwei (Word-Export) gaben wir eine weitere Schätzung ab, die einen genaueren Korridor für die verbleibende Zeit angab. Diese Schätzung beinhaltete somit einen Termin-Korridor für den Livegang der Modernisierung, der nun nur noch einen real-Monat breit war.

Tatsächlich lagen wir ab der ersten Schätzung und inklusive kleinerer Bug-Fixes nach dem Livegang gut innerhalb unseres initialen Schätzungs-Korridors. Es lohnt sich, erst grob einen Überblick über das Haupt-Feature der Anwendung zu machen (in unserem Fall das User Interface), bevor man eine erste Schätzung mit einem breiten, aber realistischen Korridor abgibt.

Big-Bang-Modernisierung? Big Lessons Learned!

Gerade bei einer Big-Bang-Modernisierung ist es wichtig, dass der Kunde konstant Zugriff auf den aktuellen Stand der Modernisierung hat. Wir hatten das große Glück, dass der Kommunikations-Kanal in Form von Chat, E-Mail und Telefon zum Kunden immer offen war, sodass falsches Verhalten oder fehlende Features in der Neu-Anwendung schnell aufgedeckt werden konnten.

Während der Modernisierung nutzten wir zwei-wöchentlich stattfindende Sprint-Meetings, um im direkten Gespräch Verständnisfragen zu lösen und ein gemeinsames Bild über den aktuellen Stand der Modernisierung herzustellen. Weiterhin erstellten wir Tickets in einem Kanban-Board, sodass der Kunde den Verlauf der Arbeit priorisieren konnte.

Zu Beginn einer Etappe war dies natürlich schwierig, da die einzelnen Aufgaben erst einmal identifiziert werden mussten. Doch sobald der erste Feature-Entwurf auf dem Testsystem war, konnte konkret analysiert werden, was noch fehlt oder anders funktionieren muss.

Mehr und öfter schätzen

Bei einer weiteren Modernisierung würde ich persönlich häufiger die Aufwandsschätzung verfeinern. Diese Modernisierung hat insgesamt knapp zwei Jahre gedauert, auch wenn die reelle Arbeitszeit weniger war.

Über diesen Zeitraum hinweg war es einfach zu wenig, sich nur zweimal bezüglich der Aufwandsschätzung zu treffen. Außerdem ist eine Schätzung in Vollzeit-Arbeitswochen des gesamten Entwicklerteams vermutlich zu abstrakt. Eine Woche ist in den Köpfen als eine Kalender-Einheit definiert und suggeriert eine feste Zeitspanne. Da aber Urlaube, Krankheitsausfälle und – in unserem Fall – Arbeit am anderen Projekt dieses Konstrukt der Vollzeit-Arbeitswoche durchaus auf mehrere reelle Wochen ausdehnen können, ist es wichtig, eine Aufwandsschätzung im Vokabular des Kunden zu finden. Ob das nun Personen-Tage oder tatsächliche Kalender-Wochen sind, muss man dann wohl vom Kunden abhängig machen. Es ist wichtig ein gemeinsames Verständnis aufzubauen, damit Transparenz hergestellt wird und es nicht zu Unzufriedenheit kommt.

Scope-Wechsel minimieren oder vermeiden

Ein weiterer wichtiger Punkt ist, dass sich das Entwickler-Team komplett auf die Modernisierung konzentrieren kann. In unserem Fall haben wir aus diesem Grund im Verlauf der Modernisierung das zweite Projekt in Absprache mit dem Kunden pausiert, um Scope-Wechsel zu vermeiden.

Weiterhin hatten wir das Glück, dass das Kern-Entwickler-Team konstant gleich blieb und somit kein Domänenwissen verloren ging. Dabei kannte ein Entwickler schon die alte Anwendung, während der andere mit komplett neuen Augen an das Projekt herangegangen ist. Das war ebenfalls eine günstige Konstellation für die Modernisierung.

Fazit

Der größte Nachteil einer Big-Bang-Modernisierung ist, dass der Kunde erst nach Abschluss der Entwicklung tatsächlich ein Produkt in Händen hält. Eine Big-Bang-Modernisierung ist sicher nicht der Idealfall für den Kunden. Bei manchen Projekten ist sie trotzdem die eine gute Alternative. Sie kann auch – wie in unserem Projekt – erfolgreich durchgeführt werden; wenn sich Entwickler-Team und Kunde konstant absprechen und sich der Schwierigkeiten vollumfänglich bewusst sind.

Falls das Projekt es zulässt, sollte man jedoch einen iterativen Modernisierungsansatz verfolgen, da der Kunde so konstant den Modernisierungsfortschritt produktiv einsetzten kann.

Für neue Blogupdates anmelden:


Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.