Ein Plan für die Legacy-Systemmigration vor der Codegenerierung
Erstellen Sie einen Plan für die Legacy-Systemmigration mit Belegen, Extraktionsreihenfolge, Paritätsprüfungen und technischen Entscheidungen.

Eine Legacy-Migration scheitert lange bevor der generierte Code offensichtlich falsch aussieht. Sie scheitert, wenn das Team ein Modell in einem einzigen Prompt auffordert, das System zu erschließen, eine neue Architektur zu wählen, verborgenes Verhalten zu erhalten, die Arbeit zu planen und das eigene Ergebnis zu bewerten. Der Prompt kann ein beeindruckendes Repository erzeugen. Eine belastbare Kette von Entscheidungen kann er nicht herstellen.
Der Plan muss vor der ersten Datei in der Zielsprache stehen. Damit meine ich mehr als einen Backlog mit Kästchen wie "Abrechnung umwandeln" und "Berichte migrieren". Ein brauchbarer Plan nennt für jedes Verhalten die Belege, die Reihenfolge ihrer Extraktion, die künftige Grenze, die es ersetzt, und den Test, der die nächste Änderung erlaubt. Bleibt eines dieser Felder leer, muss die Generierung warten.
Diese Unterscheidung zählt, weil ein Sprachmodell aus dem bereitgestellten Kontext generiert, während ein Ingenieur den Kontext finden muss, an den niemand gedacht hat. Alte Systeme verstecken Regeln in Jobsteuerung, Datenbanktriggern, Gewohnheiten der Bediener, Dateiformaten, Druckereinstellungen, Wiederholungsskripten und Ausnahmen zum Monatsabschluss. Die schwere Arbeit besteht darin, zu entscheiden, was als Verhalten gilt, und zu beweisen, dass die Ablösung es weiterhin zeigt.
Verhalten inventarisieren, bevor Dateien gezählt werden
Ein Migrationsinventar muss beobachtbares Verhalten beschreiben, nicht nur Quelldateien und Sprachanteile. Dateilisten helfen beim Schätzen der Parserarbeit, sagen aber fast nichts über den Vertrag, auf den Benutzer und verbundene Systeme bauen. Ein JCL-Schritt mit zwölf Zeilen kann entscheiden, ob die Abrechnungsdatei von gestern erneut verarbeitet wird. Ein großes Berichtsmodul kann Ausgaben erzeugen, die niemand liest.
Beginnen Sie an der Systemgrenze. Erfassen Sie jede Eingabe, Ausgabe, jedes geplante Ereignis, jede Bedienhandlung, jeden externen Aufruf, dauerhaften Speicher und jedes Fehlersignal. Sichern Sie jeweils ein echtes Beispiel und bestimmen Sie, wer die Korrektheit beurteilen kann. So entsteht eine Verhaltensoberfläche, die sich testen lässt. Erst danach ordnen Sie dieser Oberfläche Quellteile zu.
Ich verwende vier Belegklassen, weil Teams sie regelmäßig vermischen:
- Ausgeführte Belege: Produktionsanfragen, Batch-Eingaben, Datenbankänderungen, Dateien, Nachrichten und Ausgaben, die das aktuelle System tatsächlich verarbeitet hat.
- Deklariertes Verhalten: Handbücher, Schnittstellenvereinbarungen, Copybooks, Schemas, Hilfetexte und Runbooks, die beschreiben, was geschehen soll.
- Implementierte Pfade: Verzweigungen, Abfragen, Jobs, Trigger und Fehlerbehandlung im Code.
- Betriebliche Praxis: Zeitpunkte, manuelle Korrekturen, Neustartstellen und Ausnahmen, die Bediener außerhalb des Programms anwenden.
Diese Klassen können sich widersprechen. Der Widerspruch ist ein Befund und kein Ärgernis, das man glätten sollte. Verlangt das Handbuch ein Feld, während aufgezeichneter Verkehr Leerwerte enthält, muss der Migrationsplan entscheiden, ob Kompatibilität oder schriftliche Regel Vorrang hat. Eine einzelne Generierung wählt meist das Artefakt, das im Kontext am verbindlichsten wirkt. Ein Ingenieur hält den Konflikt fest, findet den Verantwortlichen und macht aus der Entscheidung einen Test.
Erstellen Sie vor dem Zielcode eine Grenztabelle. Eine kleine Version könnte so aussehen:
| Grenze | Belege | Verantwortlicher | Kompatibilitätsregel | Verifizierung |
|---|---|---|---|---|
| Nächtliche Kontodatei | Drei angenommene und eine abgelehnte Datei | Betriebsleitung | Feste Breiten und Ablehnungscode 17 bewahren | Alle vier Dateien erneut abspielen |
| Steuerberechnung | Aufgezeichnete Anfragen plus aktuelle Steuertabelle | Verantwortlicher für Finanzsysteme | Gerundete Summe und Auditfelder abgleichen | Antwort und Ledger-Zeilen vergleichen |
| Kontoauszugsdruck | Spool-Beispiele und Druckereinrichtung | Leitung Kundenservice | Seitenumbrüche und Sortierung bewahren | Benannte Fälle rendern und prüfen |
Die Tabelle legt fehlende Belege früh offen. Sie verhindert auch den üblichen Fehler, ein Datenbankschema für das gesamte Domänenmodell zu halten. Eine Spalte kann Nullwerte erlauben, weil ein fehlgeschlagener Import dort Teildaten abstellt, obwohl jede normale Transaktion einen Wert verlangt. Schemaform und fachliche Bedeutung sind verschiedene Tatsachen.
Das Migrationsledger ist der eigentliche Plan
Ein brauchbarer Plan für die Legacy-Systemmigration ist ein ausführbares Ledger aus Aussagen, Abhängigkeiten und Prüftoren. Für jeden Arbeitspunkt muss ein anderer Ingenieur fünf Fragen beantworten können: Was ändern wir, welche Belege definieren das heutige Verhalten, was muss vorher bestehen, wie vergleichen wir Alt und Neu, und wer nimmt eine beabsichtigte Abweichung ab?
Ein Ticketboard allein schafft das nicht. Tickets verändern sich, Abnahmeanmerkungen werden zu Prosa und Abhängigkeiten bleiben im Gedächtnis einzelner Personen. Halten Sie im Repository ein maschinenlesbares Ledger und beziehen Sie Reviews auf dessen Kennungen. Das Format kann YAML, JSON oder eine Datenbanktabelle sein. Entscheidend ist, dass fehlende Nachweise sichtbar bleiben.
- id: CALC-014
boundary: POST /interest/accrue
evidence:
traffic_set: traffic/interest/month_end_2025_01.ndjson
state_snapshot: snapshots/ledger_before.sql.zst
depends_on: [DATA-006, CLOCK-002]
target: services/interest/accrual.go
invariants:
- response.status == legacy.response.status
- ledger.delta_cents == legacy.ledger.delta_cents
- audit.event_type == legacy.audit.event_type
allowed_differences:
- field: response.request_id
rule: compare_presence_only
approved_by: architecture-review-27
gate: parity/CALC-014
Dieses Fragment verhindert drei Fehler. Ein Entwickler kann die Berechnung nicht ohne den steuernden Zustand testen. Nichtdeterministische Anfragekennungen erhalten eine ausdrückliche Vergleichsregel statt einer wachsenden Ignorierliste. Außerdem bindet der Eintrag die Genehmigung an eine bestimmte Abweichung, sodass später niemand still die Ausnahme erweitern kann.
Das Ledger sollte Entdeckungen von Entscheidungen trennen. "Der Legacy-Service liefert bei einer doppelten Anfrage 200" ist eine Beobachtung. "Die Ablösung bewahrt diese Antwort" ist eine Kompatibilitätsentscheidung. "Wir sollten 409 liefern" ist eine Gestaltungspräferenz. Wer diese Sätze vermischt, lässt eine wünschenswerte Bereinigung wie eine treue Migration wirken.
Schreiben Sie keine Prozentwerte wie "Modul zu 80 % migriert" in das Ledger. Prozentangaben verbergen das verbleibende Verhalten. Zählen Sie stattdessen geschlossene Tore für benannte Grenzen. Zehn kleine Berichtsvarianten wiegen keinen einzigen ungeprüften Buchungspfad auf, und der Plan muss das zeigen.
Der Plan braucht auch Abbruchbedingungen. Die Generierung stoppt, wenn Belege fehlen, eine Abhängigkeit kein verifiziertes Ziel hat, der Vergleich eine ungeklärte Differenz liefert oder kein Verantwortlicher eine beabsichtigte Änderung genehmigt hat. Ohne Abbruchbedingungen macht Termindruck aus jedem roten Ergebnis ein späteres Aufräumticket.
Von den Grenzen zum Zentrum extrahieren
Die sicherste Extraktionsreihenfolge beginnt an beobachtbaren Grenzen, führt über Datensemantik und Ablaufsteuerung und erreicht erst dann interne Algorithmen. Damit erhält jede spätere Generierung einen Vertrag und eine Messmöglichkeit. Mit dem scheinbar eigenständigsten Modul anzufangen wirkt effizient, erzeugt aber oft eine Insel mit geratenen Schnittstellen.
Erfassen Sie zuerst Ein- und Ausgaben an stabilen Übergängen. Bei einem Online-Service gehören dazu Anfragekörper, Antwortkörper, Header, Datenbankwirkungen und versandte Nachrichten. Bei einem Batch-System sind es Eingabegenerationen, Steuerkarten, Rückgabecodes, Spool-Ausgaben, erzeugte Dateien und Neustartverhalten. Bei einer Desktop-Anwendung zählen Benutzeraktionen, lokale Dateien, Berichte, Registry- oder Konfigurationszustand und Aufrufe gemeinsamer Datenbanken.
Extrahieren Sie als Nächstes die Bedeutung der Daten. Ordnen Sie Kennungen, Einheiten, Zeichencodierungen, Nullregeln, Dezimalstellen, Datumsregeln und Lebenszyklen von Datensätzen zu. Normalisieren Sie noch nicht. Ein gepacktes Dezimalfeld, ein mit Leerzeichen aufgefüllter Code und ein Zeitstempel in Ortszeit mögen unschön wirken, können aber Verhalten tragen. Erfassen Sie, wie jeder Wert ins System gelangt und wo er beobachtet wird, bevor Sie eine sauberere Darstellung wählen.
Rekonstruieren Sie dann die Ablaufsteuerung. Alte Systeme legen die fachliche Reihenfolge oft außerhalb der Fachmodule fest. JCL bestimmt, welches Programm auf einen Rückgabecode folgt. CL-Skripte wechseln Bibliotheken. Ein Shell-Wrapper wiederholt einen Befehl, den nächsten aber nicht. Ein Scheduler liefert ein Geschäftsdatum, das von der Systemuhr abweicht. Sieht die Generierung nur die aufgerufenen Programme, entstehen einzeln plausible Funktionen in der falschen Reihenfolge.
Bestimmen Sie danach Zustandsübergänge und Invarianten. Beschreiben Sie eine Transaktion als Vorzustand, Stimulus, Nachzustand und erzeugte Wirkungen. Das ist genauer als eine Prozedur nach der anderen zu übersetzen. Es legt auch Doppelverarbeitung, Teil-Commits, Ausgleichsaktionen und Wiederanlaufpunkte offen.
Erst wenn diese Schichten stehen, sollte das Team interne Implementierungen und die Zielarchitektur generieren. Die Grenzen der Zielservices müssen Verantwortlichkeit, Konsistenzbedarf und Änderungsmuster folgen. Sie dürfen nicht den Verzeichnisbaum der Quelle kopieren. Eine Eins-zu-eins-Modulübersetzung erhält zufällige Kopplung und nennt sie Modernisierung.
Es gibt eine praktische Ausnahme. Manchmal braucht man früh einen dünnen Parser oder Emulator, um Belege in einem proprietären Format zu lesen. Bauen Sie ihn als Extraktionswerkzeug, kennzeichnen Sie ihn als wegwerfbar und testen Sie ihn mit bekannten Beispielen. Lassen Sie dieses Hilfsbauteil nicht unbemerkt zur Produktionsarchitektur werden.
Belege, Deutung und Entscheidungen getrennt halten
Ingenieure brauchen getrennte Aufzeichnungen darüber, was das System tat, was sie darin erkennen und was das Projekt bewahren will. Ein langer Prompt verschmilzt alle drei zu flüssiger Prosa. Danach kann niemand erkennen, ob eine generierte Anforderung aus Verkehr, Quellcode oder Schlussfolgerung stammt.
Verwenden Sie für jedes implementierungsbestimmende Verhalten einen Aussageeintrag. Er braucht keine Zeremonie, sondern Herkunft und Status.
{
"claim_id": "BATCH-031",
"statement": "A rerun skips records already posted for the same business date",
"kind": "observed",
"evidence": ["run-884/input.dat", "run-884/ledger-after.csv", "ops-runbook-4.2"],
"confidence": "confirmed",
"decision": "preserve",
"tests": ["parity/batch_031_first_run", "parity/batch_031_rerun"]
}
Die Trennung zwischen beobachtetem und hergeleitetem Verhalten wirkt entbehrlich, bis sie einen Datenfehler verursacht. Angenommen, der Code prüft vor dem Schreiben eine Tabelle für "bereits gebucht". Ein Generator könnte daraus Idempotenz ableiten. Produktionsbelege können zeigen, dass ein bestimmtes Wiederherstellungsverfahren diese Tabelle leert und manche Wiederholungen deshalb absichtlich erneut buchen. Codepfad, Betriebspraxis und gewünschter Vertrag passen nicht zusammen. Der Eintrag zwingt das Team, den Widerspruch aufzulösen.
Behandeln Sie Kommentare als Behauptungen, nicht als Wahrheit. Das gilt ebenso für Variablennamen, tote Verzweigungen, alte Entwurfsdokumente und Tests, die nie mit produktionsähnlichem Zustand liefen. All das kann die Untersuchung lenken. Nichts davon darf ausgeführte Belege ohne benannte Entscheidung überstimmen.
Vertrauensstufen brauchen eine betriebliche Bedeutung. "Bestätigt" könnte zwei unabhängige Belegarten und die Prüfung durch einen Verantwortlichen verlangen. "Vorläufig" könnte Parserarbeit erlauben, aber die Zielimplementierung blockieren. "Unbekannt" sollte eine Extraktionsaufgabe erzeugen. Drücken die Stufen nur ein Gefühl aus, geben sie unter Termindruck nach.
Halten Sie beabsichtigte Verbesserungen in einem Änderungsregister fest, das mit der Kompatibilitätsaussage verbunden ist. Dazu gehören die Ablehnung eines ungültigen Datums, das das alte System annimmt, der Ersatz einer schwachen Authentifizierung oder ein neues Berichtslayout. Testen Sie den bewahrten Pfad und das neue Verhalten getrennt. Sonst lassen sich Paritätsfehler und beabsichtigte Verbesserung nicht unterscheiden, was Review und Rollback erschwert.
Jede Generierung endet an einem Paritätstor
Jeder Generierungsschritt muss mit einem Paritätstor enden, das beobachtbare Wirkungen mit dem aktuellen System vergleicht. Code-Review und Unit-Tests in der Zielsprache sind nötig, beweisen aber keine Kompatibilität. Sie zeigen, ob der neue Code in sich vernünftig ist, nicht ob er sich wie das benutzte System verhält.
Eine brauchbare Schleife hat fünf Schritte:
- Wählen Sie einen Ledger-Eintrag, dessen Abhängigkeiten bestanden haben.
- Stellen Sie nur seinen genehmigten Kontext zusammen: Aussagen, Schemas, Belegbeispiele, Zielvorgaben und zulässige Abweichungen.
- Generieren oder überarbeiten Sie den kleinsten Zielteil, der die Grenze erfüllen kann.
- Spielen Sie denselben Stimulus aus gleichwertigem Zustand gegen Alt und Neu ab.
- Ordnen Sie jede Abweichung ein und bestehen, überarbeiten, eskalieren oder ändern Sie den Entscheidungseintrag.
Gleichwertiger Zustand verdient Aufmerksamkeit. Beginnt der Legacy-Lauf mit dreißig Jahren Kundenhistorie und die Ablösung mit handgebauten Fixtures, beweisen gleiche Antworten wenig. Erstellen Sie einen Snapshot des relevanten Zustands, maskieren Sie ihn wo nötig, erhalten Sie referenzielle Beziehungen und dokumentieren Sie nicht reproduzierbaren Zustand. Bei Systemen, die nicht zweimal auf demselben Zustand laufen können, klonen Sie ihn oder zeichnen Wirkungen an einer Grenze auf.
Der Vergleich sollte semantisch sein, kein Rohtext-Diff. Normalisieren Sie Felder nur aus Gründen, die im Ledger stehen. Sie können Zeitstempel innerhalb einer genehmigten Toleranz vergleichen, erzeugte Kennungen ignorieren und zugleich ihr Vorhandensein verlangen, die Reihenfolge von JSON-Objekten kanonisieren oder ein PDF anhand extrahierten Textes und der Seitengeometrie vergleichen. Fügen Sie niemals eine globale Ignorierregel hinzu, nur damit ein roter Build grün wird.
Ein Paritätsbericht sollte Eintrag, Belegsatz, altes Ergebnis, neues Ergebnis, Normalisierungsregeln, Abweichungen und Entscheidung zeigen. Dieses kompakte Ergebnisformat reicht für Automatisierung und Review:
gate=CALC-014 evidence=month_end_2025_01
cases=184 matched=183 different=1 errored=0
difference[1].path=ledger.entries[2].amount_cents
difference[1].legacy=1250
difference[1].target=1249
difference[1].rule=exact
status=FAIL
Die Abweichung um einen Cent ist nicht "nah genug". Sie verweist auf Rundungsreihenfolge, Dezimaldarstellung oder einen abweichenden Zustand. Ein Ingenieur verfolgt sie durch Zwischenwerte, prüft die Rechensemantik der Quelle und ergänzt den kleinsten Test, der die Ursache isoliert. Das gesamte Modul mit einer strengeren Anweisung neu zu generieren verändert häufig fremdes Verhalten und zerstört die Beweisspur.
Führen Sie Tore laufend aus, nicht erst in einer abschließenden Abnahmephase. Eine bestandene Grenze wird zur Vorgabe für spätere Arbeit. Ändert sich eine gemeinsame Datenzuordnung, zeigt der Abhängigkeitsgraph, welche Tore erneut laufen müssen. Deshalb gehören Ledger und Harness zusammen: Das eine sagt, was sich ändern darf, das andere zeigt, was sich geändert hat.
Ein riesiger Prompt scheitert vorhersehbar
Ein einzelner Migrationsprompt scheitert, weil seine Aufgaben einander widersprechen und sein Kontext keinen Durchsetzungsmechanismus hat. Mehr Kontext kann die Erinnerung verbessern, erzeugt aber weder die Herkunft von Belegen noch eine Abhängigkeitsreihenfolge, ein unabhängiges Urteil oder ein dauerhaftes Prüftor. Das generierte Repository kann schlüssig sein und trotzdem an jeder Grenze falsch liegen, die im Prompt fehlte.
Nehmen wir eine nächtliche Abrechnungskette. Der Scheduler liefert ein Geschäftsdatum. Ein JCL-Schritt sortiert Transaktionen mit einer gebietsspezifischen Kollation. Ein Programm bucht gültige Zeilen und schreibt Ablehnungen. Ein Rückgabecode bestimmt, ob Kontoauszüge laufen. Der Betrieb kann nach dem Buchen neu starten, ohne es zu wiederholen. Die Quellmodule enthalten Teile dieses Verhaltens, aber kein einzelnes Modul besitzt den gesamten Vertrag.
Ein großer Prompt fordert eine Neufassung in Go und enthält Programme, Copybooks, Beispieldateien sowie den Satz "Verhalten bewahren". Das Ergebnis verwendet das Maschinendatum, sortiert Zeichenketten mit dem Standard der Ziellaufzeit, packt den Batch in eine einzige Datenbanktransaktion und behandelt jede Ablehnung als fatalen Fehler. Jede Entscheidung wäre in einem neuen System vertretbar. Zusammen zerstören sie den Monatsabschluss.
Die erste Testdatei enthält normale Datensätze, deshalb berechnen beide Systeme dieselben Summen. Das Team freut sich. Der erste Neustart wiederholt Buchungen, weil das Ziel keinen zum Legacy-Schritt passenden Prüfpunkt hat. Eine Datei mit leerem Kontosuffix sortiert anders, wodurch sich die Gruppierung ändert. Eine einzige schlechte Zeile rollt jetzt gültige Arbeit zurück, die die alte Kette gebucht hätte. Keiner dieser Fehler sieht wie ein Syntaxdefekt oder eine offensichtlich schlechte Gestaltung aus.
Eine geplante Extraktion hätte sie der Reihe nach gefunden. Die Grenzerfassung hält Geschäftsdatum und Rückgabecodes fest. Die Datenanalyse erfasst Kollation und Leerzeichenfüllung. Die Orchestrierungsanalyse hält Commit- und Neustartpunkte fest. Der Replay umfasst normale, abgelehnte und fortgesetzte Läufe. Die Zielarchitektur darf die Implementierung weiterhin verbessern, aber diese Verträge nicht versehentlich löschen.
Die beliebte Antwort lautet, den Prompt länger zu machen. Das hilft nur, wenn Auslassung das einzige Problem ist. Es erschwert die Auflösung von Konflikten, verschüttet die Beleggrundlage einzelner Anweisungen und lässt den Generator weiterhin seine eigene Arbeit beurteilen. Auch mehrere Agenten lösen das nicht automatisch. Sie brauchen dasselbe Ledger, dieselben Verantwortungsregeln und Paritätstore, sonst verteilen sie unbelegte Annahmen nur schneller.
Nutzen Sie Generierung als begrenzten Implementierungsvorgang. Geben Sie ihr einen Zielteil, ausdrückliche Vorgaben, die dafür nötigen Belege und die fehlgeschlagene Paritätsausgabe des vorherigen Versuchs. Prüfen Sie danach die Änderung und führen Sie das Tor außerhalb des Generierungsprozesses aus. Diese Teilung hält das Modell produktiv, ohne ihm eine Verantwortung zu übertragen, die es nicht tragen kann.
Der Ingenieur verantwortet das Ungeklärte
Ein Ingenieur übernimmt die Arbeit, die sich nicht auf plausiblen Code reduzieren lässt: fehlende Belege finden, den maßgeblichen Widerspruch bestimmen, Grenzen wählen, bewusste Änderungen aushandeln und Risiko akzeptieren. Das sind keine vorübergehenden Lücken, die mit größeren Modellen verschwinden. Es sind Verantwortungsakte in einer bestimmten Organisation.
Der Ingenieur fragt, wer leidet, wenn zwei Artefakte widersprechen. Erlaubt der Quellcode eine Überziehung, die Finanzrichtlinie aber nicht, braucht es eine Produkt- und Compliance-Entscheidung statt einer wahrscheinlichkeitsgewichteten Synthese. Verlassen sich Bediener auf einen Neustarttrick, den das neue Design beseitigen soll, muss der Ingenieur seinen Grund verstehen, einen sichereren Wiederherstellungspfad entwerfen und Zustimmung zum bewussten Kompatibilitätsbruch einholen.
Der Ingenieur kontrolliert auch die Zerlegung. Ein Generator folgt meist der sichtbaren Struktur. Der Ingenieur kann erkennen, dass sechs Programme eine Konsistenzgrenze bilden oder ein Monolith vier unabhängig verantwortete Fähigkeiten enthält. Dieses Urteil stützt sich auf Transaktionssemantik, Deploymentbedarf, Störungshistorie und die Menschen, die das Ziel pflegen werden.
Reviews sollten vor dem Stil die Aussagen und Wirkungen prüfen. Fragen Sie, welchen Ledger-Eintrag die Änderung schließt, welche Belege sie nutzt, welche Zielentscheidung sie verkörpert und was der Paritätsbericht sagt. Ein schön idiomatischer Service mit ungeklärter Ausgabedifferenz ist unfertig. Ein unbequemer Adapter, der eine schwierige Grenze erhält, kann genau das richtige Zwischenbauteil sein.
Ingenieure müssen das Harness auch davor schützen, zum Abnickwerkzeug zu werden. Jede Normalisierungsregel braucht einen Grund. Jede Golden File braucht eine Herkunft. Jedes geänderte erwartete Ergebnis braucht dieselbe Prüfung wie eine Änderung des Produktionsverhaltens. Aktualisiert das Team Snapshots bei jedem Fehlschlag, hat es eine Genehmigungsmaschine statt eines Paritätsharness gebaut.
Geschwindigkeit bleibt möglich. Generieren Sie Parser, Adapter, Tests, Zuordnungscode und Implementierungskandidaten parallel, wenn die Ledger-Abhängigkeiten es erlauben. Halten Sie Belegbeschaffung und Torergebnisse zentral. Parallele Codeproduktion ist nützlich; parallele Wahrheit ist ein Widerspruch.
Architektur ändert sich nur hinter bewiesenen Verträgen
Modernisierung sollte die Architektur hinter bewahrten Verträgen ändern, nicht die alte Struktur Zeile für Zeile übersetzen. Sobald eine Grenze Belege und ein Paritätstor hat, kann das Team gemeinsamen Zustand durch ausdrückliche Services ersetzen, numerische Kerne isolieren, Daten nach Postgres verschieben oder einen TypeScript-Client bauen, ohne zu raten, ob die neue Form das sichtbare Verhalten geändert hat.
Entscheiden Sie Architektur auf der kleinsten Ebene, für die genügend Belege vorliegen. Manche Entscheidungen gehören an den Anfang: Vorgaben der Ziellaufzeit, Sicherheitsgrenzen, Deploymentumgebung, Datenstandort und Systeme, die während der Umschaltung nebeneinander laufen müssen. Andere sollten warten: Serviceaufteilungen, Cache-Platzierung, asynchrone Grenzen und Schemabereinigung hängen oft von Verhalten ab, das erst bei der Extraktion erscheint.
Meiden Sie beide Extreme. Jedes Zieldetail vor der Entdeckung einzufrieren erzeugt einen eleganten Plan für ein vorgestelltes System. Jede Generierung ihre eigene Architektur erfinden zu lassen erzeugt widersprüchliche Grenzen und doppelte Infrastruktur. Erfassen Sie bindende Entscheidungen, halten Sie vertagte Entscheidungen sichtbar und benennen Sie die Belege, die sie schließen werden.
Die Umschaltplanung gehört in dasselbe Ledger. Benennen Sie während des Übergangs die maßgebliche Datenquelle, Synchronisierungsrichtung, Abstimmabfrage, Rollback-Punkt und maximal akzeptierte Unterbrechung. Eine Ablösung kann isolierte Paritätstests bestehen und betrieblich trotzdem scheitern, wenn beide Systeme dieselben Datensätze schreiben oder ein Rollback nur im Ziel entstandene Änderungen nicht zurückholen kann.
CodeHero arbeitet nach diesem Muster, wenn es einen gesamten Legacy-Baum liest, ihn in Go, Rust, TypeScript und Postgres neu schreibt und das Verhalten mit einem Paritätsharness gegen aufgezeichneten Produktionsverkehr prüft. Das Lieferversprechen von unter 30 Tagen hängt von der engen Ordnung aus Extraktion und Verifizierung ab; der Plan wird dadurch nicht entbehrlich.
Verlangen Sie vor der Freigabe der ersten generierten Zieldatei einen vollständigen Ledger-Eintrag mit echten Belegen, ausdrücklichen Abhängigkeiten, einer Vergleichsregel und einem benannten Verantwortlichen für Abweichungen. Kann das Team diesen Eintrag nicht liefern, ist es nicht migrationsbereit. Es kann nur Code erzeugen, der wie migriert aussieht.
FAQ
Warum kann ein einziger langer Prompt kein Legacy-System migrieren?
Ein langer Prompt kann eine schlüssig wirkende Codebasis erzeugen, aber er kann weder festlegen, welche Belege maßgeblich sind, noch Konflikte zwischen Code, Betrieb und Richtlinien genehmigen. Er kann auch kein unabhängiges Urteil zur Kompatibilität abgeben, wenn er sein eigenes Ergebnis bewertet.
Was sollte ein Plan für eine Legacy-Migration enthalten?
Erfassen Sie für jede Verhaltensgrenze die Belege, Abhängigkeiten, das Ziel, die Invarianten, zulässige Abweichungen, das Prüftor und den Verantwortlichen für Entscheidungen. Der Plan braucht außerdem Abbruchbedingungen, damit fehlende Belege oder ungeklärte Abweichungen die Generierung blockieren.
Was sollte ein Team zuerst aus Legacy-Code extrahieren?
Beginnen Sie mit beobachtbaren Eingaben, Ausgaben, geplanten Ereignissen, Bedienhandlungen, dauerhaften Auswirkungen und Fehlersignalen. Extrahieren Sie danach Datensemantik und Ablaufsteuerung, bevor Sie interne Algorithmen implementieren, denn diese Grenzen geben der späteren Arbeit einen Vertrag.
Wie verifiziert man die Neufassung eines Legacy-Systems?
Spielen Sie denselben Stimulus gegen das alte und das neue System aus gleichwertigem Zustand ab und vergleichen Sie jede beobachtbare Wirkung anhand schriftlicher Normalisierungsregeln. Ordnen Sie jede Abweichung als Defekt, genehmigte Änderung, Belegproblem oder Umgebungsproblem ein.
Reichen Unit-Tests für eine Legacy-Migration aus?
Nein. Unit-Tests zeigen, dass der Zielcode den Erwartungen seiner Autoren entspricht, während Paritätstests zeigen, ob er dem abzulösenden System entspricht. Sie brauchen beides, denn eine saubere Implementierung kann eine falsche Annahme sehr genau umsetzen.
Können KI-Agenten eine vollständige Code-Migration planen?
Agenten können Code inventarisieren, Zuordnungen vorschlagen, begrenzte Teile generieren und fehlgeschlagene Tests untersuchen. Ingenieure bleiben für die Qualität der Belege, die Reihenfolge der Abhängigkeiten, Architekturentscheidungen, Konfliktlösung und die Abnahme bewusster Verhaltensänderungen verantwortlich.
Sollte eine Modernisierung jedes Legacy-Verhalten bewahren?
Nein, aber jede Abweichung sollte beabsichtigt sein. Halten Sie den alten Pfad in einem Paritätstest fest, erfassen Sie die genehmigte Änderung separat und testen Sie die neue Regel, damit eine gewünschte Bereinigung keinen anderen Kompatibilitätsfehler verdeckt.
Wie behandelt man nichtdeterministische Felder in Paritätstests?
Schreiben Sie eine enge Vergleichsregel, die etwa das Vorhandensein einer Kennung statt ihres exakten Werts verlangt oder eine dokumentierte Zeittoleranz zulässt. Verwenden Sie niemals eine breite Ignorierliste, denn sie verdeckt an anderer Stelle bedeutsame Unterschiede.
Wann sollte die Zielarchitektur festgelegt werden?
Legen Sie harte Vorgaben und Sicherheitsgrenzen früh fest und verschieben Sie Entscheidungen, die vom entdeckten Verhalten abhängen. Bestimmen Sie Servicezuschnitte, Datenbereinigung und asynchrone Abläufe erst, wenn Belege zeigen, welche Konsistenz- und Verantwortungsgrenzen gelten müssen.
Was ist das erste Prüftor vor der Generierung von Migrationscode?
Vervollständigen Sie einen Ledger-Eintrag mit echten Ein- und Ausgabebelegen, bekannten Abhängigkeiten, ausdrücklichen Invarianten, Vergleichsregeln und einem Verantwortlichen für strittige Ergebnisse. Ist dieser Eintrag unvollständig, muss das Team weiter extrahieren, statt Produktionscode zu generieren.