Irgendwann kann der Punkt erreicht sein, an dem eine bestehende Anwendung an seine Grenzen stößt und die Anforderungen an eine Software gestiegen sind. Sei es aufgrund einer Expansion ins Ausland, Integrationen von externen Systemen oder des hohen Wartungsaufwandes.
Die Gründe dafür sind vielfältig wie das Leben selbst.
Die gute Nachricht ist, bei der Migration spielt es keine Rolle ob das Legacy System eine ältere Excel Applikation ist, mit Oracle Forms gebaut wurde oder eine alte Windows Forms ERP Anwendung ist.
Das Vorgehen bei der Migration ist stets die gleiche.
Migrationsstrategie
Die Migrationsstrategie ist vor allem für Anwendungen mit umfangreicher Geschäftslogik geeignet. Bei einfachen Datenverwaltungsanwendungen kann auch der unten genannte Ansatz mit Scaffolding genutzt werden.
1. Bestandsanwendung in kleine Anwendungsfälle (Use-Cases / Features) schneiden, welche für sich genommen einen eigenen Prozessablauf innerhalb des Softwaresystems abbilden. Diese müssen beschrieben, aufgegliedert und in das Backlog aufgenommen werden.
Es sollte nach Möglichkeit vermieden werden, Code einer anderen Programmiersprache lesen zu müssen, da dieser ebenfalls fehlerhaft sein könnte und unter Umständen schwer zu verstehen ist.
2. E2E (End-to-End) Implementierung der Use Cases mit regelmäßiger (2-3 Wochen) Vorstellung der Implementierungsergebnisse, bei der ein Use-Case auf Basis einer sauberen Softwarearchitektur vollständig implementiert wird.
Dabei muss darauf geachtet werden, dass der bestehende Code bestehen bleibt und nur eine Kopie von vorhanden Code gemacht wird.
Neu schreiben ist meist einfacher als ändern.
3. Ursprünglichen Code als veraltet (obsolete) kennzeichnen.
4. Testen des neuen Features.
5. Verwendung und Nutzung des neuen Features anstatt des Ursprünglichen.
6. Alten Code entfernen / archivieren.
Datenbank wiederverwenden und scaffolden?
Mit dem Scaffolding kann eine Datenbank genutzt werden um daraus Quellcode in C# zu generieren. Es kann dazu genutzt werden um das C# Model (Entitäten) zu generieren, einen DBContext zu erzeugen und darauf aufbauend Controller und MVC Ansichten zu generieren.
So erhält man in kürzester Zeit eine einfache CRUD Anwendung die zur Verwaltung von Daten über einen Browser zugänglich macht.
Wenn die Anwendung tatsächlich nur der Datenverwaltung dient und sonst keine umfangreichen Geschäftsprozesse abbildet sollte das Vorgehen genügen.
Andernfalls kann der schnelle Weg auch schnell zum Verhängnis werden, wenn versucht wird, eine bestehende, evtl. nicht kompatible Datengrundlage auf ein neues System zu überführen, da manche Tabellen ggf. zu systemspezifisch sind oder Spalten nur aushilfsweise (z.B. Lookup, Rolling Fields) angelegt wurden. In diesem Fall, sollte die oben genannte Migrationsstrategie zur schrittweisen Implementierung einzelner Use-Cases / Features genutzt werden.
Migrationsprojekte wirken kleiner als sie sind
Migrationsprojekte wirken auf dem ersten Blick häufig so, als könnten Sie einfach und schnell zu bewerkstelligen werden, da der Code meist bereits vorhanden ist, fachliche Themen geklärt wurden und die Datengrundlage schon vorhanden ist.
Aus meiner Erfahrung heraus, ist dem allerdings meistens nicht so und die Projekte werden mit zu geringer Projektlaufzeit eingeplant.
Die Gründe warum Migrationsprojekte länger brauchen als erwartet:
- Bestehender (Legacy) Code kann nicht wiederverwendet werden.
Der Code ist entweder in einer anderen Programmiersprache geschrieben oder ist zu sehr abhängig von einer Anwendung (z.B. Excel, Oracle) und/oder der darunter liegenden Infrastruktur (Datenbank, Betriebssystem, externe Systeme, etc.). - Legacy Code soll verstanden und transformiert werden.
Auch wenn man als Entwickler meist auch andere Programmiersprachen und deren Logik versteht, ist es häufig mit erheblichen Anstrengungen verbunden ihn zu analysieren, erst recht wenn auf gängige Clean Code Prinzipien verzichtet wurde. - Mangelnde Kooperation mit den späteren Usern.
Der Bedarf nach einer neuen Anwendung ist meist aus Userperspektive nicht sehr groß, da sie bereits mit der aktuellen Legacy Anwendung vertraut sind und alles soweit mehr oder weniger funktioniert wie es für den täglichen Arbeitsalltag gebraucht wird.
Doch für eine schnelle und zielgerichtete Umsetzung werden die konkreten Anforderungen der User gebraucht, da nur Sie wissen, welche Funktionen der Anwendung wirklich genutzt werden und wie sie damit arbeiten möchten. - Komplexe (oder fehlende) IT-Architektur und Implementierungsstrategie
„Wenn schon neu entwickeln, dann aber richtig.“
Nicht selten werden bei der Migration auf ein neues System gleich die neuesten Technologien und Systemarchitekturen eingesetzt, ohne zu wissen wie diese richtig funktionieren oder warum Sie überhaupt genutzt werden sollen. Das kostet neben hohen Einarbeitungsaufwand, nicht selten auch hohe Cloudgebühren. - Überorganisieren des Projektes (Bürokratie)
Das Management und die Koordination eines Projektes ist natürlich wichtig und sollte nicht unterschätzt werden.
Doch das Schreiben von unzähligen Tests, Dokumentationen, pflegen von Zeiten, Velocity, Kalender, Einarbeitung neuer Kollegen, Entscheidungsreports, Meetings kostet Entwicklungszeit die unter Umständen effektiver eingesetzt werden kann.
Auch wenn Vieles davon sicherlich sinnvoll ist, bleibt abzuwägen ob es der richtige Zeitpunkt ist und/oder es überhaupt den Preis (die Zeit) Wert ist, der dafür bezahlt wird.
Wie die Migration gelingt
Nachdem die Gründe für langen Migrationsprojektlaufzeiten genannt wurden, sollen die folgenden Strategien dabei helfen, dass das Projekt möglichst effektiv umgesetzt werden kann:
- 100% Commitment und Engagement bei Sponsoren und Usern:
Sponsoren und User der Anwendung müssen zu 100% commited sein und sich in das Projekt mit einbringen. Sie müssen wissen WARUM sie die Legacy Anwendung migriert haben wollen und die Vorteile darin sehen.
Das Engagement der User ist außerdem unabdingbar um das Backlog der Anwendung mit sinnvollen Features zu füllen. Ohne ihr regelmäßiges Feedback, werden Features ins blaue geraten und nicht zielgerichtet umgesetzt. - Denke End to End(E2) und KISS: Keep it simple and stupid
Es sollte nur das implementiert werden was auch wirklich gebraucht wird (YAGNI) und die Anwendung anfangs einfach gehalten sein. Dazu genügt ein einfacher Webserver der eine ASP.NET API hostet, eine einfache View über Angular oder Razor und das war es auch schon.
Auf hochskalierbare Microservice Architekturen und Cloud Services kann anfangs verzichtet werden. Wenn die Anwendung auf Basis von Clean Architecture umgesetzt wird, ist sie modular und Wiederverwendbar und Teile davon können später als eigenen Use-Case in einem eigenen (Micro-)Service laufen und skaliert werden, wenn eine bessere Performance benötigt wird.
Der Fokus sollte dabei auf die Implementierung und das Testen eines konkreten Geschäftsablaufes folgen, der in sich geschlossen ist und unabhängig von anderen Prozessen (Abläufen) ausgeführt werden kann. Andere Features sollten zu dem Zeitpunkt ausgeblendet werden. - Neu schreiben und nicht kopieren
Das neu schreiben von Code ist meist effektiver als bestehenden Code zu kopieren und wiederzuverwenden. Außer der Code hat bereits eine hohe Kohäsion und eine geringe Kopplung vorzuweisen und kann daher einfach als eigene Komponente oder Service bereitgestellt und in die neue Anwendung integriert werden. - Das richtige Timing
Der Fokus sollte zunächst darauf liegen, eine einfache Web-Anwendung zu programmieren und die alte Legacy Anwendung zu ersetzen, deren Funktionsumfang sie zu 100% abbildet.
Zusätzliche Features wie Autorisierung/Authentifizierung, Mehrsprachigkeit, Zeitzonen Variabilität etc., Dokumentationen, E2E Tests kommen zu der Zeit an der ihr Fundament stabil genug ist und Veränderungen nur noch selten vorkommen.
Ansonsten potenziert sich die Entwicklungszeit immer zusätzlich zu den aufbauenden Systemartefakten (höheren Abstraktionsschichten).
