Ganz ehrlich? Lass wegwerfen und Microservices machen!
Oft klingt die Lösung verführerisch: Über Bord mit dem alten System, um dann einmal alles neu zu entwickeln. Frisch, modern und fit für die Zukunft. Oder können wir das alte System vielleicht noch einmal aufmöbeln? Eine schwierige Diskussion, die wahrscheinlich täglich in unzähligen Unternehmen stattfindet.
Wer mit IT zu tun hat, der weiß: Keine Software ist für die Ewigkeit gebaut. Software altert sozusagen -- und mit dem Alter kommen die Wehwehchen:
- Zeitgemäße Features können nicht unterstützt werden
- Die Implementierung neuer Funktionen gestaltet sich zäh und die Aufwandsschätzungen werden zunehmend ungenauer
- Die Tools der Entwicklung (IDEs, Frameworks, Libraries, ...) sind veraltet und fühlen sich in der Handhabung in etwa an, als würde man versuchen, mit einer Zahnbürste das Firmengelände zu kehren
- Gefühlt endlose Bugfix-Runden, die in zahllose neue Bugs resultieren
- Das System wird langsam, instabil und aufwändig in der administrativen Handhabung. Inzwischen gesellen sich zum Unmut aus der Produktentwicklung auch die Beschwerden der Kund:innen, die zunehmend über Abstürze und lange Ladezeiten klagen.
Warum Software altert, hat verschiedene Gründe. Teils kommen die Gründe aus der Produktentwicklung selbst, teils handelt es sich aber auch um externe Faktoren, die man als Hersteller der Software kaum beeinflussen kann. Ein paar Gedanken dazu finden Sie auch in diesem Artikel von mir. Im nächsten Schritt stellt sich die Frage, wie man die Softwareentwicklung wieder auf den richtigen Kurs bringt. Da diese kosten- und zeitintensive Entscheidung mit einigen Risiken einhergeht, sollten konkrete Maßnahmen gut evaluiert werden.
Also lassen Sie uns einen Blick auf die verfügbaren Optionen werfen:
Überarbeitung der Bestandssoftware
Wenn Sie ein Haus bauen und nach zehn Jahren ein paar Mängel feststellen, ist Ihr erster Gedanke wahrscheinlich nicht direkt der Verkauf des Hauses, sondern eine Reparatur. Ähnlich könnte man sich bei einem Bestandssystem fragen: Warum können wir das System nicht einfach aufmöbeln und wieder auf Vordermann bringen? Und ja, unter gewissen Umständen geht das schon:
Einerseits können wir durch Restrukturierung des Quellcodes gezielt dessen Qualität anheben, ohne dabei das sichtbare Programmverhalten zu verändern (Refactoring). Andererseits können wir einzelne sichtbare Bereiche der Software umbauen, um etwa ein besseres Nutzererlebnis zu erreichen.
Eine solche Überarbeitung kann inkrementell und kleinschrittig erfolgen und ist daher vergleichsweise risikoarm. Allerdings werden auch beim Refactoring tiefe Einschnitte in das System gemacht, z.B. in zentrale Datenstrukturen, das Datenbankschema oder in kritische Prozessabläufe. Daher ist eine gut aufgestellte Qualitätssicherung beim Refactoring sehr wichtig.
Anmerkung am Rande: Das Refactoring sollte eigentlich sowieso regelmäßige Routine in jeder guten Entwicklungsarbeit sein. Quellcode verliert durch häufige Überarbeitung leider beständig ein wenig an Qualität. Nur durch aktiv eingeplante Gegenmaßnahmen kann man größere Probleme verhindern. Vorteil ist eine langfristig höhere Wartbarkeit und Fehlerfreiheit des Quellcodes.
Die Überarbeitung ist zwar vergleichsweise risikoarm, allerdings sind die erzielbaren Veränderungen eher kleinschrittig und insgesamt begrenzt, da man sich ja weiterhin im gleichen System bewegt, von dem man einen Großteil erhalten möchte. Im Folgenden ein paar Voraussetzungen, die meines Erachtens für eine sinnhafte Überarbeitbarkeit der Bestandssoftware wichtig sind:
- Der Tech Stack kann so bleiben. Das Bestandssystem hat zwar Probleme, jedoch stimmt die technologische Basis für die Zukunft. Das System ist also beispielsweise nicht in Turbo Pascal geschrieben, während die Entwicklungsabteilung hauptsächlich aus davon genervten Java-Expert:innen besteht.
- Eine gründliche Qualitätssicherung ist leistbar. Tiefgreifende strukturelle Änderungen am Quellcode gehen damit einher, dass neue Fehler eingebaut werden. Das Verhalten des Systems sollte also durch hinreichend viele Testfälle (manuell wie automatisiert) validierbar sein. Eine gute Voraussetzung wäre etwa eine weitreichende Testabdeckung der kritischen Bereiche in Form automatisierter Modul- und Integrationstests. Das ist sehr leicht daher gesagt -- erfahrene Entwickler:innen wissen, dass sich hier die Katze häufig in den Schwanz beißt: In Bestandssystemen gibt es oft wenige Tests und Komponenten lassen sich aufgrund einer verwobenen Struktur schwer testen. Man müsste also zunächst Refactoring betreiben, um eine bessere Testbarkeit des Codes zu erreichen. Tests sind aber wiederum eine wichtige Grundlage für das Refactoring. Hier kommt es auf die richtige Teststrategie an, welche im Team vorab detailliert besprochen werden sollte.
- Das System ist kein "Big Ball of Mud". Dabei handelt es sich um ein System, welches kaum oder keine erkennbare Architektur besitzt und bei dem fast niemand einen Überblick über das Gesamtsystem hat. In solchen Fällen kann man zwar auch Refactoring betreiben, aber wahrscheinlich ist der Aufwand größer als wenn man alles gleich wegwirft.
- Sorgfältige Planung und Priorisierung der Maßnahmen. Refactoring sollte nicht wahllos erfolgen. Die größten Probleme sollten beschrieben, bewertet, zeitlich abgeschätzt und priorisiert werden. Welche Module sind aus Business-Sicht die wichtigsten? Welche Module werden am Häufigsten erweitert und modifiziert, wo muss die Wartbarkeit besonders gut sein? Wo verstecken sich wertvolle Quick-Wins?
Eine neue Generation der Software von Grund auf entwickeln
Kommen wir nun zur Abrissbirne in unserem Werkzeugkoffer. Nicht selten entsteht in Unternehmen die Idee, eine Nachfolgegeneration der Bestandssoftware von Grund auf neu zu schreiben. In aller Regel mit dem Ziel, grundsätzlich andere Technologien und methodische Vorgehensweisen zum Einsatz zu bringen. Aus dem Bestandssystem werden allenfalls noch einzelne Aspekte übernommen, etwa bewährte Datenstrukturen oder algorithmische Verfahren.
Vorteilhaft ist bei diesem Ansatz, dass relativ ballastfrei eine schlanke, neu erdachte Version des Bestandssystem entstehen kann. Man hat die Gelegenheit, Technologien wie auch methodische Ansätze der Entwicklung einmal grundsätzlich zu tauschen und kann vergleichsweise mühelos neue Benutzeroberflächen und Nutzererlebnisse (evtl. auch auf neuen Geräten) schaffen, ohne sich zu viele Gedanken darüber machen zu müssen, wie die bisherige Infrastruktur damit klarkommt.
Das klingt natürlich verlockend. In der Praxis scheitern jedoch viele solcher Projekte oder benötigen ein Vielfaches der anberaumten Zeit und Kosten. Woran liegt das?
Im Folgenden schauen wir uns einige typische Fallstricke an:
- Das Bestandssystem, welches neu geschrieben werden soll, wächst weiter. Nur wenige Unternehmen sind in der luxuriösen Situation, dass sie die Bestandssoftware in der Weiterentwicklung faktisch einfrieren können. Häufig müssen beständig neue Features, Plugins und kundenspezifische Sonderfunktionen implementiert werden. Neben der Neuentwicklung muss also auch das Bestandssystem weiterentwickelt werden, dessen Umfang immer größer wird. In manchen Unternehmen verteidigt man die Neuentwicklung dann damit, dass man die bisherige Funktionalität ja in einer neuen, modularen Architektur viel schneller und besser integrieren könne, wenn einmal der neue Kern der neuen Software stünde. In vielen Fällen ist dies jedoch eine Illusion. Nach einigen Monaten Entwicklung erzeugt der Markt oft Druck, sodass dann in Windeseile die Funktionen der Bestandssoftware in den Kern der neuen Softwaregeneration reingeprügelt werden. Damit werden die initialen Bemühungen einer sauberen und wartbaren Software-Architektur wieder zunichte gemacht.
- Das Team welches die neue Softwaregeneration entwickelt, ist unerfahren in Bezug auf das Business. "Die Neuentwicklung muss ja qualitativ viel besser werden, schließlich haben wir die Erfahrung aus dem Bestandssystem und kennen unsere Fachdomäne sehr gut" -- vielleicht haben Sie solche Argumente auch schon gehört. Oft wird aber eine wichtige Voraussetzung vergessen: die Entwickler:innen, welche die Erfahrungen aus der bisherigen Entwicklung gesammelt haben, müssen an der Neuentwicklung auch tatsächlich beteiligt sein. Nicht selten werden in der Neuentwicklung aber eher Entwickler:innen eingesetzt, die frisches technisches Know-How mitbringen, aber die Fachdomäne noch nicht so gut kennen und bislang wenig an der Bestandssoftware entwickelt haben. Wenn ein Team zum Großteil aus neuen Kolleg:innen zusammengestellt wird, gibt es keinen Grund anzunehmen, dass die Softwarequalität der neuen Generation per se höher sein wird, als es beim Bestandssystem der Fall war. Viel wahrscheinlicher ist, dass einige Fehler von damals wiederholt werden.
- Die Fachdomäne muss neu ergründet werden. Doch selbst wenn man erfahrene Entwickler:innen im Team hat, muss das nicht heißen, dass die Umsetzung der Fachdomäne ein Spaziergang wird. Das Fachwissen über existierende Prozesse, Regeln und Daten ist häufig sehr ungleich in Teams verteilt, eventuell auch auf Köpfe, die heute gar nicht mehr im Unternehmen sind. Auch erfahrenen Expert:innen passiert es, dass sie fachliche Aspekte mit der Zeit einfach vergessen. Wozu war nochmal diese Sonderbehandlung hier im Archivierungsprozess der Bestellhistorie gut? Die braucht doch niemand. Bis man merkt, dass ein einziger Kunde alle 6 Monate mal bei der Reporterstellung eine zusätzliche Kennzahl anhakt, deren korrekte Generierung von eben dieser Sonderbehandlung abhängt. Man muss sich an dieser Stelle einfach bewusst machen, dass die fachliche Sicht auf eine Software in aller Regel von unzähligen Details abhängt. Diese muss man auf dem Schirm haben, möchte man einen erfolgreichen Nachfolger der bisherigen Software bauen.
Aus diesen Punkten lassen sich einige Voraussetzungen ableiten, die für den Erfolg einer Neuentwicklung wichtig sind:
- Entwicklung und Vertrieb müssen an einem Strang ziehen. Alle Stakeholder sind sich über den Aufwand einer Neuentwicklung bewusst und die Bedingungen am Markt erlauben ein solches Unterfangen, auch wenn das Projekt in Verzug kommen sollte.
- Die Fachdomäne wird sehr gut verstanden. Je einfacher die Fachdomäne, desto risikoärmer die Neuentwicklung. Je komplexer die Fachdomäne, desto wichtiger ist, dass diese in der Neuentwicklung stark vertreten wird. Hier muss das Product Ownership entsprechend aufgestellt sein: Werden alle Features, Sondermodule und Funktionen und deren Funktionsweise wirklich verstanden? Können diese mit klaren Akzeptanzkriterien in Form von Requirements bzw. User-Stories dokumentiert werden?
- Das Team aus der Bestandsentwicklung ist maßgeblich an der Entwicklung beteiligt. Dabei kann es natürlich durch technisches Know-How von weiteren Kolleg:innen bzw. von einer externen Beratung ergänzt werden. Jedoch sollten die Personen, welche die Erfahrung aus dem bisherigen System vertreten können, eine wichtige Rolle in der Neuentwicklung spielen.
Schrittweise Überführung eines Bestandssystems
Je nach Art der Software bietet sich zu den obigen beiden Vorgehensweisen noch eine Alternative an, nämlich die schrittweise Überführung des Bestandssystems in eine neue Generation der Software. Dabei würde man einen kleinen Teil der Software vom Gesamtsystem abtrennen, und nur diesen Teil komplett neu entwickeln. Das neue (Mini-)System wird nun mit dem Bestandssystem über eine Adapterlösung integriert, sodass die beiden Systeme gemeinsam den bisherigen Funktionsumfang der Software wie gewohnt abdecken.
Wiederholt man dieses Vorgehen über mehrere Releases hinweg, kann man zunehmend Teile des Bestandssystems durch eine neue Softwaregeneration ersetzen, wobei die Software aber insgesamt funktionsfähig und erweiterbar bleibt.
Den Schnitt durch das Bestandssystem kann man nicht wahlfrei vornehmen. Vielmehr ergeben sich durch die fachlichen Zusammenhänge und architektonischen Gegebenheiten natürliche Fugen
in der Software, an denen eine Auftrennung besonders gut möglich ist. Eine sorgfältige Systemanalyse ist für ein solches Vorhaben also unabdingbar. Gegebenenfalls muss auch ein Refactoring einzelner Systemteile als Vorbereitung durchgeführt werden.
Die schrittweise Überführung ist nicht bei jeder Art von Software möglich. Serverseitige Systeme sind eher dafür geeignet als clientseitige Systeme und auch bei einer Serversoftware kommt es darauf an, wie diese betrieben wird. Betreibt der Endkunde das System, muss dieser ggfs. die technischen Voraussetzungen für die neue und ältere Technologiebasis gleichermaßen schaffen, was unter Umständen schwierig zu verargumentieren ist.
Welche Strategie wählt man nun?
Die Frage nach der Zukunftsstrategie einer Software bleibt schwierig und ist im Einzelfall von sehr vielen Parametern abhängig.
Als Faustregel sollte man meines Erachtens jedoch immer zuerst die Überarbeitung der Bestandssoftware durch Refactoring in Betracht ziehen. Trotz aller Probleme und Unschönheiten älterer Software ist es im Allgemeinen so, dass sich Bestandssysteme im laufenden Betrieb vielfach beweisen konnten und zahlreiche Verbesserungen in Form von Bugfixes und Stabilisierungen erfahren haben. Dies ist eine sehr kostbare Eigenschaft eines jeden Systems, die man sich in vielen Fällen über zig Personenjahre Entwicklungszeit mühevoll erkauft hat. Die Neuentwicklung from scratch
bedeutet, diese Investition wegzuwerfen.
Entscheidet man sich für die Neuentwicklung, sollte man unbedingt die Machbarkeit eines solchen Vorhabens mit allen Stakeholdern kritisch evaluieren, insbesondere im Hinblick auf den Markt, die Zusammenarbeit zwischen Entwicklung und Vertrieb und der Verfügbarkeit von Fachexpert:innen, welche genug Zeit haben, um die Neuentwicklung im Bereich des Anforderungsmanagements zu begleiten.
Bei der axio concept GmbH beschäftigen wir uns schwerpunktmäßig mit den Themen Software-Architektur und der Modernisierung von Bestandssoftware. Wenn Sie selbst gerade vor einer ähnlichen Herausforderung stehen und eine zweite Meinung benötigen, können Sie mich sehr gerne kontaktieren.