In der Softwarewelt können fünf Jahre sowohl ein System bedeuten, das weiterhin sehr gut für die weitere Entwicklung vorbereitet ist, als auch ein technologisches Problem, das mit jedem weiteren Monat mehr kosten wird.
Das Alter einer Anwendung allein ist jedoch kein Grund, sie zu ersetzen.
Das ist eines der wichtigsten Dinge, die man gleich zu Beginn sagen sollte.
Es gibt keine universelle Grenze, nach der eine Anwendung neu geschrieben werden muss. Es gibt Systeme, die seit über einem Dutzend Jahren laufen und dennoch eine sinnvolle Architektur, aktuelle Abhängigkeiten, gute Dokumentation und einen bewährten Bereitstellungsprozess haben. Es gibt auch deutlich jüngere Anwendungen, deren Weiterentwicklung durch falsche architektonische Entscheidungen, fehlende Tests, unkontrollierte Abhängigkeiten oder weitere schnelle Fixes erschwert wurde.
Das Problem ist also nicht die Anzahl der Jahre.
Das Problem ist die Fähigkeit des Systems zur weiteren Veränderung.
Die wichtigste Frage lautet nicht: "Ist die Anwendung alt?"
Die bessere Frage lautet: "Wie viel kostet uns die nächste Änderung?"
Wenn das Hinzufügen einer neuen Funktion immer mehr Stunden, die Einbindung mehrerer Teams, manuelle Tests und das Umgehen der Einschränkungen einer alten Architektur erfordert, erzeugt das System Kosten, die im Code selbst nicht sichtbar sind.
Das ist eines der praktischen Anzeichen für wachsende Technical Debt.
Technical Debt kann als Kosten zukünftiger Änderungen verstanden werden, die aus früheren technischen Entscheidungen resultieren. Martin Fowler beschreibt sie als zusätzlichen Aufwand, der bei der Modifikation eines Systems entsteht, wenn seine innere Qualität die Weiterentwicklung erschwert.
Genau deshalb kann eine Anwendung weiterhin korrekt funktionieren und zugleich immer schwieriger weiterzuentwickeln sein.
10 Funktionen später sieht das System ganz anders aus
Der Beginn eines Projekts ist oft einfach.
Ein MVP entsteht.
Dann kommen weitere Anforderungen hinzu:
- Integration mit dem CRM,
- Online-Zahlungen,
- Administrationsbereich,
- Mobile App,
- neue Benutzerrollen,
- Berichterstattung,
- Automatisierungen,
- API,
- Integrationen mit externen Diensten,
- weitere Sprachversionen.
Jede Änderung für sich genommen kann sinnvoll sein.
Das Problem entsteht, wenn die Architektur nicht mit Blick auf eine solche Entwicklungsrichtung entworfen wurde.
Dann werden weitere Funktionen nicht mehr an eine stabile Struktur angehängt.
Sie werden an frühere Ausnahmen, Umgehungen und Kompromisse angefügt.
Woran erkennt man, dass ein System zu altern beginnt?
Man muss nicht auf einen kompletten Ausfall warten.
Warnsignale treten viel früher auf.
1. Eine neue Funktion dauert immer länger
Früher dauerte eine Funktion ein paar Tage. Heute erfordert eine ähnliche Änderung mehrere Wochen.
Das muss nicht bedeuten, dass das Team langsamer ist.
Es kann bedeuten, dass immer mehr Zeit darauf verwendet wird, das bestehende System zu verstehen und es vor den Folgen der Änderung zu schützen.
2. Jede Änderung löst einen Dominoeffekt aus
Die Änderung eines Moduls verursacht Probleme an mehreren anderen Stellen.
Das ist ein Zeichen dafür, dass die Komponenten zu stark miteinander verknüpft sind oder die Verantwortungsgrenzen zwischen ihnen falsch definiert wurden.
3. Tests sind größtenteils manuell
Wenn jede größere Änderung eine manuelle Überprüfung von Dutzenden Funktionen erfordert, steigen die Einführungskosten.
Das Problem ist nicht der fehlende Grad an Automatisierung an sich.
Das Problem ist die fehlende Möglichkeit, schnell verlässliche Informationen darüber zu erhalten, ob etwas durch die Änderung beschädigt wurde.
4. Das Team hat Angst, bestimmte Teile des Systems anzufassen
Das ist ein sehr praktischer Indikator.
Wenn es Module gibt, die Entwickler meiden, weil "niemand genau weiß, was nach einer Änderung passiert", ist das technische Risiko bereits zu einem realen Geschäftskostenfaktor geworden.
5. Das System hängt von veralteten Technologien ab
Ein altes Framework ist für sich genommen noch kein Problem.
Das Problem entsteht, wenn:
- es nicht mehr unterstützt wird,
- es schwierig ist, Spezialisten zu finden,
- Abhängigkeiten nicht sicher aktualisiert werden können,
- die Laufzeitumgebung problematisch ist,
- die Integration mit neuen Lösungen erschwert wird.
Dann beginnt die Technologie, die geschäftlichen Möglichkeiten zu begrenzen.
Muss man die Anwendung immer neu schreiben?
Nein.
Das ist einer der häufigsten Fehler im Umgang mit Legacy-Software.
Ein vollständiger Rewrite kann gerechtfertigt sein, ist aber ein Vorhaben mit hohem Risiko.
Ein altes System enthält oft Dutzende oder Hunderte von Geschäftsregeln, Ausnahmen und Verhaltensweisen, die in der Dokumentation fehlen. Wenn man es von Grund auf neu schreibt, kann man sehr leicht ein technologisch neues, aber geschäftlich unvollständiges System schaffen.
Deshalb ist in vielen Fällen die bessere Lösung eine schrittweise Modernisierung.
Ein Teil des Systems bleibt aktiv, während weitere Bereiche schrittweise durch neue Komponenten ersetzt werden.
Ein solcher Ansatz ist u. a. als Strangler-Fig-Muster bekannt. Er ermöglicht es, das System Schritt für Schritt zu modernisieren, früher Wert zu liefern und das Risiko einer einmaligen Migration der gesamten Lösung zu reduzieren.
Wann ist Modernisierung sinnvoll?
Es lohnt sich, sie zu erwägen, wenn:
- das System weiterhin wesentliche Geschäftsprozesse abbildet,
- die Architektur es erlaubt, zumindest einen Teil der Funktionalität auszugliedern,
- Daten sicher migriert oder integriert werden können,
- das Problem bestimmte Bereiche betrifft und nicht die gesamte Struktur,
- die Anwendung Wert schafft und ein vollständiger Ersatz riskant wäre,
- das System schrittweise modernisiert werden kann.
Das ist besonders eine gute Lösung bei Systemen, die man nicht einfach für mehrere Monate abschalten kann.
Wann kann Modernisierung keinen Sinn mehr haben?
Es gibt auch Situationen, in denen das weitere Retten eines alten Systems wirtschaftlich nicht mehr sinnvoll ist.
Zum Beispiel wenn:
- die Architektur grundlegend nicht mit den aktuellen Anforderungen vereinbar ist,
- zentrale Technologien nicht mehr unterstützt werden,
- dem System verlässliche Tests und Dokumentation fehlen,
- die Sicherheit eine grundlegende Überarbeitung erfordert,
- jede größere Änderung Eingriffe in nahezu das gesamte System erfordert,
- es an Menschen fehlt, die seine Funktionsweise verstehen,
- die Kosten für Wartung und Weiterentwicklung den Wert der weiteren Nutzung übersteigen.
Dann sollte man nicht nur die Kosten der Modernisierung berechnen.
Man muss auch die Kosten des Verbleibs bei der aktuellen Lösung berechnen.
Die teuerste Anwendung ist nicht immer die mit den höchsten Wartungskosten
Man kann ein System haben, dessen monatlicher Betrieb relativ wenig kostet.
Und gleichzeitig kostet jede neue Funktion ein Vielfaches dessen, was sie kosten sollte.
Deshalb sagt die bloße Rechnung für Hosting, Server oder Support noch nicht, wie viel die Technologie wirklich kostet.
Die wahren Kosten eines Systems umfassen auch:
- Entwicklungszeit,
- Testzeit,
- Kosten von Fehlern,
- Einführungszeit,
- Kosten von Ausfällen,
- Schwierigkeit bei der Rekrutierung,
- Sicherheitsrisiko,
- Kosten des Wissensverlusts,
- Verzögerung neuer Funktionen,
- geschäftliche Einschränkungen, die sich aus der Technologie ergeben.
Irgendwann hört Technologie auf, ein Werkzeug zur Unterstützung des Geschäfts zu sein.
Sie wird zur Einschränkung des Geschäfts.
Wie geht man an die Entscheidung heran?
Bevor die Entscheidung "wir schreiben es neu" fällt, lohnt es sich, ein technisches Audit durchzuführen.
Es sollte mindestens Folgendes umfassen:
Architektur - wie das System aufgeteilt ist und wie seine Elemente miteinander kommunizieren.
Code - Qualität, Komplexität, Wiederholbarkeit und besonders schwer zu wartende Stellen.
Abhängigkeiten - Frameworks, Bibliotheken, Versionen und deren Unterstützung.
Sicherheit - Schwachstellen, die Art der Zugriffsverwaltung und Risiken, die sich aus veralteten Komponenten ergeben.
Tests - der Umfang der Automatisierung und die Möglichkeit, Änderungen sicher einzuführen.
CI/CD - die Art und Weise, wie die Anwendung gebaut, getestet und bereitgestellt wird.
Daten - die Struktur der Datenbank, Migrationen, Integrationen und Abhängigkeiten.
Monitoring - ob man weiß, was nach dem Deployment mit dem System passiert.
Entwicklungsprozess - wie viel die Lieferung einer weiteren Funktion tatsächlich kostet.
Erst auf dieser Grundlage kann man die drei Szenarien rational erwägen:
- wir warten und entwickeln weiter,
- wir modernisieren schrittweise,
- wir bauen ein neues System.
Es gibt keine eine richtige Antwort. Es gibt jedoch den richtigen Weg, zur Antwort zu gelangen.
Technologie sollte Entwicklung ermöglichen und sie nicht blockieren
Gute Architektur besteht nicht darin, dass ein System modern aussieht.
Sie besteht darin, dass man es dann ändern kann, wenn das Geschäft es erfordert.
Deshalb lohnt es sich, eine Anwendung nicht nur durch die Brille zu betrachten, ob sie heute funktioniert.
Man muss auch prüfen, wie viel es kosten wird, in einem, zwei oder fünf Jahren weitere Funktionen hinzuzufügen.
Denn ein System, das funktioniert, aber eine effiziente Weiterentwicklung verhindert, kann ein viel größeres Problem sein als ein System, das einfach nur modernisiert werden muss.
