Komplizierte Anwendungen agil migrieren
Eine Grundidee von agilen Methoden in der Software-Entwicklung ist es, Anwendungen iterativ zu entwickeln und in Betrieb zu nehmen. Für neue Software funktioniert das sehr gut. Wie gehen wir aber damit um, wenn eine bestehende, komplizierte Software abgelöst werden muss?
Die agilen Methoden in der Softwareentwicklung sind entstanden aus der Einsicht, dass in unserer komplexen und dynamischen Welt wenige Dinge im Voraus feststehen. Software-Entwicklungsprojekte lassen sich nicht gut planen, da am Ende einer langen Umsetzung oftmals die ursprünglichen Anforderungen nicht mehr aktuell sind. Die agile Software-Entwicklung geht deshalb in Schritten vor. Als erstes wird in kurzer Zeit ein sogenanntes MVP gebaut, das Minimal Viable Product. Dieses stellt einen möglichst kleinen Kern der zu entwickelnden Software dar, der aber für sich bereits funktionsfähig sein soll. Davon ausgehend wird die Software iterativ weiterentwickelt, wobei sie nach jedem Schritt mindestens theoretisch wieder voll lauffähig und produktiv einsetzbar wäre. Durch dieses fortgesetzte Verfeinern, Produktivsetzen und Lernen aus der tatsächlichen Nutzung, kann das Produkt sehr zielgerichtet entsprechend der tatsächlichen, aktuellen Kundenbedürfnisse entwickelt werden. Darüber hinaus sorgt dieses Vorgehen dafür, dass echter Nutzwert bereits sehr früh realisiert wird.
Was ist das MVP bei der Ablösung einer vorhandenen Applikation?
Agilität ist ein sehr eleganter und praktikabler Ansatz der Software-Entwicklung. Was aber, wenn keine neue Anwendung gebaut und deshalb Kundenbedürfnisse nicht erst gefunden werden müssen? Wenn es darum geht eine bestehende, komplizierte Applikation abzulösen oder zu migrieren, die im schlimmsten (und damit Normal-) Fall auch noch in eine ganze Applikationslandschaft eingebunden ist? Unter diesen Umständen ist es oft schwierig mit einem Minimal Viable Product anzufangen und dieses iterativ zu verbessern. Wenn wir eine Applikation ablösen, müssen meist mindestens die vorhandenen Funktionalitäten auch in der neuen Applikation wieder verfügbar sein. Auch die Schnittstellen zu umliegenden Systemen sind für ein Funktionieren der Gesamtprozesse oft unverzichtbar.
Ist ein iterativ-agiles Vorgehen hier also unangebracht? Müssen wir klassisches Projektmanagement mit Wasserfallmethodik anwenden?
Angesichts der schon im Vorhinein bekannten Anforderungen wäre ein klassisches Projektmanagement-Ansatz tatsächlich geeignet. Dennoch wäre es von Vorteil, könnten wir iterativ vorgehen: Der Nutzen der neuen Applikation könnte frühzeitig und nicht erst am Ende des Projektes realisiert werden. Außerdem besteht auch im Falle einer Migration das Risiko, dass die realen Anforderungen sich bis zum Projektende verändern. Viel schlimmer wäre es noch, wenn der Anwendungsfall für die Software gänzlich entfällt – sei es wegen regulatorischer Vorgaben, weil der Anwendungsfall insgesamt wegfällt oder aus anderen Gründen. In diesen Fällen wäre ein Ansatz vorteilhaft, bei dem wir schon frühzeitig einen (Teil-) Nutzen erzielen.
Wie kann das funktionieren? Tatsächlich ist das nicht ganz einfach umzusetzen. Um bei einem Migrationsprojekt iterativ vorzugehen, müssen wir Blöcke von Funktionalitäten identifizieren, die für sich lauffähig sind und aufeinander aufbauend entwickelt werden können. Hierin liegt die intellektuelle Herausforderung beim “Agilisieren” eines Migrationsprojektes.
Die Migration von Altsystemen ist eine echte Herausforderung
Iteratives Migrieren bedeutet Parallelbetrieb über einen langen Zeitraum
Beim “Agilisieren” eines Migrationsprojektes ist die Idee, die ersten Versionen der neuen Applikation parallel zur vorhandenen Applikation zu betreiben. Alle Anwendungsfälle, die mit den ersten Blöcken von Funktionalitäten umsetzbar sind, werden anstatt auf der alten auf der neuen Applikation durchgeführt. Kompliziertere Anwendungsfälle verbleiben solange auf der Bestandsapplikation, bis die hierfür nötigen Funktionalitäten in der neuen Applikation vorhanden sind. Diese entwickeln wir entsprechend den Funktionsblöcken iterativ und nehmen sie regelmäßig in den Produktivbetrieb. Auf diese Weise können wir iterativ die Anwendungsfälle migrieren und profitieren vom Nutzen der neuen Applikation so früh wie möglich (beispielsweise schnelleren Verarbeitungszeiten, Auditierbarkeit des Prozesses, Einhaltung von Compliance-Anforderungen…). Ein sehr gut geeignetes Hilfsmittel für den Product Owner zum Planen der Funktionsblöcke ist übrigens das sogenannte Story Mapping.
Natürlich erfordert dieses Vorgehen auch, dass wir uns zusätzliche Gedanken machen wie ein Parallelbetrieb der alten und neuen Anwendung funktionieren kann. Wir müssen uns überlegen, was passiert, wenn ein ehemals einfacher Anwendungsfall auf die neue Applikation migriert wurde, dann aber unerwartet zu einem komplizierteren wird, der noch nicht umgesetzt ist. Auch Abhängigkeiten der Daten in der neuen und alten Applikation können ein größeres Hindernis sein. All diese Probleme lassen sich nur im konkreten Einzelfall klären.
Agile Migration am Beispiel von idealo
Darum genug der Theorie. Ein Beispiel aus der Praxis von idealo, Deutschlands großem Preisvergleich und Shoppingportal, macht die Idee anschaulicher. idealo importiert mit spezialisierten Import-Applikationen täglich rund eine Milliarde Angebotsdaten von Online-Händlern. Da die Datenmengen seit Jahren kontinuierlich steigen, war die in einer Import-Applikation verwendete Datenbank irgendwann am Rande ihrer Leistungsfähigkeit und ließ sich auch nicht mehr sinnvoll skalieren. Der Neubau der gesamten Applikation mit einer optimierten Importlogik wurde unausweichlich. Natürlich hatte die Import-Applikation unzählige, auch komplizierte Funktionalitäten für verschiedene Händler und natürlich war sie eingebettet in vielfältige Prozesse. Andererseits war nicht klar, wann die sichtlich überlastete Datenbank ganz zusammenbrechen würde. In diesem dringend zu vermeidenden Fall wäre gar kein Import mehr möglich gewesen – ein katastrophales Szenario.
Um nun eine Migration iterativ umsetzen zu können, haben wir die Funktionalitäten der Anwendung in Blöcke geschnitten. Wie bereits angedeutet, ist dieses Schneiden von unabhängigen Funktionsblöcken die schwierigste Herausforderung. In unserem Fall haben wir die Funktionalitäten entsprechend ihrer Nutzung durch unterschiedliche Händlergruppen getrennt. Beispielsweise versenden einige deutsche Händler auch nach Österreich, so dass deren Angebote für die deutsche und das österreichische idealo-Seite verfügbar gemacht werden müssen, inklusive Unterschieden bei Mehrwertsteuer, Lieferzeiten und weiteren Details. Also haben wir das Importieren von deutschen Händlern, die auch nach Österreich versenden, in einem späteren Funktionsblock geplant. Dementsprechend konnten wir bis zur Umsetzung dieses Blockes auch nur die Händler auf die neue Applikation migrieren, die nach Deutschland, aber nicht nach Österreich versenden. Ein anderer Funktionsblock umfasste die Funktionalität mit Varianten von Angeboten umzugehen. Ein Beispiel für ein variantisiertes Angebot wäre ein Handy, das in unterschiedlichen Farben und Speichergrößen verkauft wird. Wenn diese unterschiedlichen Ausprägungen nicht als eigenständige Angebote, sondern als Optionen eines Angebotes geliefert werden, sprechen wir von Varianten. Auch das Importieren von Varianten wurde für einen späteren Block von Funktionalitäten geplant. Bevor dieser vollständig umgesetzt wurde, konnten wir mit der neuen Applikation bereits Händler importieren, die keine Varianten in ihren Angeboten verwendeten.
Auch wenn das Vorgehen soweit hoffentlich nachvollziehbar klingt, ist es gar nicht so einfach zu identifizieren, welche konkreten Funktionsblöcke ein einzelnen Händler benötigt. Insgesamt importieren wir über die Applikation ca. 560.000 Händler. Entsprechend können wir die nötigen Funktionsblöcke für jeden Händler nur automatisiert identifizieren. Ebenso müssen wir hoffen, dass ein Händler, der zum Beispiel bisher noch nie Varianten verwendet hat, nicht plötzlich damit anfängt. Wir hätten sonst ein Problem, falls er schon auf die neue Applikation migriert wurde und diese den Umgang mit Varianten noch nicht beherrscht.
(Test-) Automatisierung lohnt sich
Um diese Herausforderungen in den Griff zu bekommen, haben wir in Tests und Automatisierung investiert. Circa ein Drittel der Gesamtaufwände machte das am Ende aus. Dafür war selbst die Migration vollautomatisiert. Unser Setup umfasste zwei Teststrecken: die alte und die neue Importstrecke. Automatisch wurde ein Händler mit all seinen Angeboten parallel über den alten und den neuen Importer importiert und die Ergebnisse beider Importe am Ende verglichen. Lagen keine unerklärbaren Abweichungen vor, wurde der Händler durch unsere Testapplikation automatisch auf die neue Import-Applikation umgestellt. Auf diese Weise wurde jeder Händler automatisiert migriert, sobald das für ihn möglich war.
Was hat uns dieses iterative Vorgehen mit dem doch umfangreichen Testaufwand genutzt?
Der wichtigste Vorteil war, dass wir die knapp vor dem Zusammenbruch stehende Datenbank der alten Applikation zeitnah um die ersten migrierten Händler entlasten konnten. Damit sank bereits sehr früh im Projekt das absolut kritische Betriebsrisiko signifikant. Auch von zusätzlichen Features in der neuen Applikation konnten wir frühzeitig profitieren. Ein Beispiel war die individuelle Steuerung der Importfrequenz pro Händler, wenn natürlich auch nur für die bis dahin migrierten Händler. Darüberhinaus war ein Nebeneffekt unseres gründlichen Testvorgehens, dass wir sogar noch fachliche Fehler in der alten Applikation entdeckt und behoben haben und somit die Qualität auch der Angebotsdaten der alten Applikation noch steigern konnten.
Fazit
Es lohnt sich auch für die Migration komplizierter Bestands-Applikationen über einen agilen, d. h. iterativen Ansatz nachzudenken. Geeignete Schnitte für die Iterationen zu finden ist nicht einfach, da oft viele Funktionalitäten und Schnittstellen gleich zu Beginn vorhanden sein müssen. Die Kunst liegt darin, die Anwendungsfälle der zu verarbeitenden Daten nach der Komplexität ihrer funktionalen Anforderungen zu unterteilen. Unter Umständen lassen sich so Blöcke von Funktionalitäten finden, die in Iterationen nacheinander umgesetzt werden können und jeweils schon die Migration einer Teilmenge der Anwendungsfälle, Daten etc. erlauben. Der dabei stattfindende Parallelbetrieb der alten und neuen Applikation wiederum bringt Herausforderungen mit sich, die gründlich bedacht sein müssen. Automatisierung und Testen sind die Mittel der Wahl, um dies zu beherrschen. Der Gesamtaufwand eines solchen Projektes mag vielleicht etwas höher sein als der einer Wasserfall-Migration. Der dafür wesentlich früher realisierbare Nutzen und das signifikant reduzierte Risiko gegenüber einer späten Big-Bang-Migration dürften das in den meisten Fällen jedoch deutlich aufwiegen.
Hallo Herr Hegewald,
danke für den sehr interessanten Beitrag. Warum schreiben Sie denn von komplizierter und nicht von komplexer Software?
Sonnige Grüße
Michael Schenkel
Hallo Herr Schenkel,
eine gute Frage. Es geht bei Bestandssoftware tendenziell eher um kompliziert und nicht komplex.
Bei “komplizierten” Vorhaben steht von vornherein halbwegs fest, was zu tun ist und ich muss es eigentlich nur abarbeiten.
Bei “komplexen” Vorhaben hingegen weiß ich noch gar nicht, was zu tun ist.
Im Fall von Bestandssoftware könnte man theoretisch alle vorhandene Funktionalität einfach hernehmen und neu umsetzen. Man wüsste dann vorab relativ genau, was zu tun ist. Das ist aber nur kompliziert und nicht komplex. Gerade deshalb läge es auch nahe ein Wasserfall-Vorgehen anstatt agiler Methoden zu verwenden. Hier ist ein vielleicht spannender Artikel dazu: http://www.leanovate.de/blog/noch-kompliziert-oder-schon-komplex-systeme/
Herzliche Grüße
Jan Hegewald