Die Demo funktioniert. Erste Nutzer kommen hinzu. Dann führt eine Preisänderung zu fehlerhaften Buchungen, eine Korrektur der Berechtigungen betrifft drei Bildschirme, und niemand weiss, warum zwei Services denselben Betrag unterschiedlich berechnen. Sie haben gerade das Repository übernommen.
Für Entwickler oder CTOs beginnt die Übernahme mit einer Frage: Können wir die Folgen der nächsten Änderung vorhersagen? Die Antwort hängt von Geschäftsregeln, Grenzen im Code und verfügbaren Möglichkeiten ab, das Verhalten zu prüfen.
Unser Artikel zu Nutzen und Grenzen von Vibe Coding hilft bei der Einordnung. Der Leitfaden zur Übernahme einer Anwendung behandelt Audit und Produktivbetrieb. Hier geht es ins Repository: Tests, Vokabular, Module, Architekturentscheide und Migrationen.
Das Risiko: Code, den das Team nicht mehr erklären kann
Generierter Code kann gut konzipiert, geprüft und getestet sein. Eine vollständig von Hand geschriebene Anwendung kann dieselben Probleme ansammeln. Die Herkunft des Codes sagt wenig über seine Weiterentwickelbarkeit aus; prüfen Sie sein Verhalten und die Entscheide hinter seiner Struktur.
Der DORA-Report 2025 beschreibt KI als Verstärker der Stärken und Schwächen einer Organisation. Das ist keine Bewertung Ihres Repositorys. Für eine Übernahme folgt daraus: Verständnis und Validierung stärken, bevor die Codeproduktion wieder beschleunigt wird.
Besonders kritisch ist ein Symptom: Niemand kann eine Regel erklären, ohne die ganze Anwendung nachzuverfolgen oder ein Modell um Rekonstruktion zu bitten. Eine plausible Erklärung bleibt eine Hypothese, bis ausgeführter Code, Tests und Fachexperten sie bestätigen.
Vor dem Refactoring: eine Referenzversion schaffen
Beginnen Sie mit einer reproduzierbaren Umgebung, einer identifizierten Codeversion, gesperrten Abhängigkeiten und Testdaten. Prüfen Sie, ob das Team den Service bereitstellen und wiederherstellen kann. Verfolgen Sie danach einen kritischen Ablauf vom Bildschirm über die Speicherung bis zu externen Diensten.
Entdecken Sie Datenexposition, unberechtigte Zugriffe oder kompromittierte Secrets, behandeln Sie dieses Risiko vor der Architekturarbeit. Ordner umzustrukturieren macht eine unsichere Anwendung nicht sicher.
Wählen Sie anschliessend einen ersten Umfang: eine Geschäftsfähigkeit, die sich oft ändert, Incidents verursacht oder einen Release blockiert. Die folgenden fünf Bereiche lassen sich innerhalb dieses Umfangs behandeln, bevor sie auf den Rest der Anwendung ausgedehnt werden.
1. Testbarkeit verbessern, bevor Regeln geändert werden
Charakterisierungstests von Michael Feathers erfassen, was ein Programm tatsächlich tut. Sie helfen, Verhaltensänderungen bei einer Übernahme zu erkennen, selbst wenn die ursprüngliche Spezifikation fehlt. Sie beweisen nicht, dass dieses Verhalten wünschenswert ist.
Betrachten wir eine fiktive Buchungsanwendung. Beobachten Sie vor einer Neuorganisation des Codes eine bestätigte Buchung, eine Stornierung und eine wiederholte Anfrage nach Netzunterbruch. Halten Sie Antworten und Effekte fest: Buchungsstatus, Datenbankschreibvorgänge und gesendete Benachrichtigungen.
Validieren Sie erwartete Ergebnisse getrennt mit Fachexperten. Erlaubt das aktuelle Verhalten zwei Bestätigungen für den letzten freien Platz, bewahren Sie eine Reproduktion des Fehlers und schreiben Sie einen Test für das korrigierte Ergebnis. Ein bekannter Fehler darf nicht zur Anforderung werden, nur um bestehendes Verhalten zu erhalten.
Testbarkeit verbessert sich, wenn Abhängigkeiten kontrollierbar sind. Trennen Sie die Berechnung einer Frist vom Lesen der Uhr und den Entscheid zur Bestätigung vom Aufruf eines Zahlungsanbieters. Testen Sie Regeln ohne Netzwerk und prüfen Sie Adapter sowie Datenbankvorgaben mit Integrationstests.
- Geschäftsregeln: Ablauf, Stornierung, Teilrückerstattungen und Preisänderungen.
- Integrationen: parallele Anfragen für den letzten Platz, verzögerte Antworten und doppelte Ereignisse.
- Kritische Abläufe: Bestätigung für den richtigen Nutzer und verweigerter Zugriff aus einer anderen Organisation.
Für den CTO ist das erste erwartete Ergebnis eine nützliche Änderung, die durch diese Tests abgesichert ist. Gesamtabdeckung kann zusätzliche Hinweise geben, ersetzt aber keine Prüfung der tatsächlichen Produktrisiken.
2. Eine gemeinsame Fachsprache etablieren
Eine Anwendung kann dasselbe Objekt in der Oberfläche «Buchung», in der API «Auftrag» und in der Datenbank «Sitzung» nennen. «Kunde» kann zudem eine angemeldete Person, eine Organisation oder ein Abrechnungskonto meinen. Diese Mehrdeutigkeit betrifft irgendwann Berechtigungen und Geschäftsregeln.
Die von Martin Fowler aus Eric Evans’ Domain-Driven Design erläuterte Ubiquitous Language bringt das Vokabular der Entwickler mit jenem der Fachexperten zusammen. Sie entwickelt sich mit dem Verständnis des Teams weiter.
| Begriff | Vereinbarte Bedeutung | Zu prüfende Regel |
|---|---|---|
| Hold | Temporär reservierter Platz | Hat eine explizite Ablaufzeit |
| Booking | Bestätigte Buchung | Respektiert verfügbare Kapazität |
| Payment | Zahlungsvorgang | Sein Status unterscheidet sich vom Buchungsstatus |
| Organization | Zugriffsgrenze eines Teams | Liest keine Buchungen anderer Organisationen |
Diese Definitionen müssen für das konkrete Produkt validiert werden. Storniert eine fehlgeschlagene Zahlung die Buchung oder beginnt eine Nachfrist? Code allein kann nicht entscheiden, was das Unternehmen will.
Übernehmen Sie die vereinbarten Begriffe in Typen, Operationen, Tests und Fachbereichsdokumentation. Halten Sie explizite Übersetzungen für ältere APIs fest. Zwei Bereiche dürfen unterschiedliche Wörter verwenden; sie künstlich zusammenzuführen würde neue Mehrdeutigkeit schaffen.
Ein Code-Agent sollte diese Definitionen und Invarianten erhalten, bevor er Änderungen vorschlägt. Sie geben Reviewern zudem konkrete Kriterien zur Annahme oder Ablehnung eines Vorschlags.
3. Tiefe Module mit einfachen Verträgen erstellen
Ein tiefes Modul stellt hinter einer relativ einfachen Schnittstelle umfangreiche Funktionalität bereit. In seiner Diskussion mit Robert C. Martin erklärt John Ousterhout, weshalb die Vermehrung kleiner Funktionen Komplexität verteilen statt verringern kann.
In unserem Beispiel prüft vielleicht jeder Bildschirm Verfügbarkeit, berechnet Preise, erstellt Buchungen und sendet Benachrichtigungen. Zusätzliche Helper-Dateien lassen dennoch jeden Aufrufer für die korrekte Koordination verantwortlich.
Eine Geschäftsoperation wie confirmBooking kann einen sinnvolleren Vertrag anbieten: authentifizierte Identität, betroffene Buchung, Idempotenzschlüssel und mögliche Ergebnisse. Das Modul koordiniert die Bestätigungsregeln; Aufrufer können auch zwischen fehlender Verfügbarkeit, verweigertem Zugriff und ausstehender Zahlung unterscheiden.
Eine kurze Schnittstelle genügt nicht. Ihr Vertrag muss Effekte und Fehler beschreiben. Eine lokale Transaktion macht einen externen Anbieteraufruf nicht atomar: Zwischenzustand, Wiederaufnahme nach Fehlern und Vermeidung von Duplikaten müssen explizit bleiben.
Suchen Sie nach zusammenhängenden Verantwortlichkeiten: Buchung, Abrechnung und Identität. Sie können im selben Deployment leben. Die Extraktion von Mikroservices würde Netzwerk- und Betriebsanforderungen hinzufügen, die eine eigene Begründung brauchen.
Abnahmekriterium: Eine Änderung der Bestätigungsregel verändert das Modul und seine Tests; Aufrufer bleiben stabil, solange sich der Vertrag nicht ändert. Dateianzahl und Dateilänge sagen ohne diese Prüfung wenig aus.
4. Überraschende Entscheide mit ADRs erklären
Code zeigt, wie eine Lösung funktioniert, lässt aber ihren Grund manchmal unsichtbar. Warum zwei Identifikatoren behalten? Warum ein Ereignis asynchron verarbeiten? Warum vorübergehend zwei Formate akzeptieren?
Ein Architecture Decision Record oder ADR hält einen wesentlichen Entscheid, seinen Kontext, Status und Folgen fest. Michael Nygard schlägt kurze, mit dem Code versionierte Dokumente vor, die ältere Entscheide bei ihrer Ablösung weiterhin zugänglich lassen.
Ein ADR für unser Beispiel kann enthalten:
- Kontext: Der Anbieter kann dasselbe Zahlungsereignis mehrmals liefern.
- Entscheid: Ereignis-ID speichern und Verarbeitung idempotent gestalten.
- Verworfene Option: Jede Lieferung als neue Zahlung annehmen.
- Folgen: Eindeutigkeit in der Datenbank, Wiederaufnahme nach Fehlern und Tests paralleler Lieferungen definieren.
- Status: Akzeptiert, mit Links zu Implementierung und Tests.
Bei einer Übernahme kann ein Agent helfen, Belege für einen Entscheid zu finden. Fehlt die Historie, halten Sie fest, dass die Begründung noch bestätigt werden muss. Eine heute erfundene Rechtfertigung ist nicht das Gedächtnis des Projekts.
Reservieren Sie ADRs für strukturelle Entscheide. Eine lokale Bedingung braucht möglicherweise nur einen präziseren Namen oder einen Kommentar zu ihrer Vorgabe. Nützliche Dokumentation verhindert, dass eine spätere Änderung einen missverstandenen Schutz entfernt.
5. Wiederholte Migrationen automatisieren
Ist der Zielvertrag validiert, müssen manchmal Dutzende Aufrufstellen angepasst werden. Das eignet sich für einen Codemod: eine Code-Transformation, die Sie prüfen, testen und wiederholen können.
jscodeshift bietet Werkzeuge, um mehrere JavaScript- oder TypeScript-Dateien anhand ihrer Syntaxstruktur zu transformieren. Damit zielt eine Transformation auf Codeformen, statt Text unterschiedslos zu ersetzen.
In unserem Beispiel könnte eine Transformation Aufrufe des alten Buchungsservice ersetzen, deren Parameter dem neuen Vertrag entsprechen. Mehrdeutige Fälle sollten bei der manuellen Prüfung bleiben. Ein Syntaxbaum allein beweist nicht, dass zwei Operationen dieselbe geschäftliche Bedeutung haben.
- Testen Sie die Transformation mit Vorher-/Nachher-Beispielen, auch mit Dateien, die sie ignorieren muss.
- Prüfen Sie einen Testlauf auf kleinem Umfang sowie Imports, Aliase und Signaturen.
- Wenden Sie Änderungen in Batches an und führen Sie danach Typprüfung, Tests und Diff-Review aus.
- Prüfen Sie, dass eine zweite Ausführung nichts mehr verändert, und erfassen Sie verbleibende alte Aufrufe.
Eine Code-Migration migriert Daten nicht automatisch. Bei inkompatiblen API- oder Schemaänderungen trennt Danilo Satos Parallel-Change-Pattern drei Phasen: erweitern, migrieren und zurückbauen.
Führen Sie ein neues, für den Übergang geeignetes Format ein, migrieren Sie Konsumenten und Daten und prüfen Sie danach, dass keine alten Leser oder Schreiber verbleiben. Erst dann entfernen Sie das alte Format. Schreiben beide Systeme parallel, definieren Sie auch, wie Abweichungen erkannt und korrigiert werden.
Ein Rollback muss transformierte Daten und externe Effekte berücksichtigen. Nach dem Löschen einer Spalte oder dem Senden einer Benachrichtigung genügt die Rückkehr zum vorherigen Commit nicht.
Was ein CTO entscheiden muss
Entscheiden Sie nach Geschäftsfähigkeit. Eine nutzbare Oberfläche kann bleiben, während das Berechtigungsmodul ersetzt werden muss. Martin Fowlers Strangler-Fig-Ansatz liefert einen Rahmen, um ein System schrittweise zu ersetzen und Ergebnisse während des Übergangs zu bewerten.
| Beobachteter Zustand | Möglicher Entscheid | Erwarteter Nachweis |
|---|---|---|
| Verhalten verstanden, stabil und geprüft | Behalten | Die nächste Änderung bleibt lokal und testbar |
| Zuverlässige Regeln, zu stark gekoppelte Abhängigkeiten | Schrittweise refaktorieren | Verhaltenstests bleiben gültig |
| Fragiles Subsystem mit identifizierbarer Grenze | Isolieren, dann ersetzen | Vertrag und Migrationsstrategie geprüft |
| Modell passt nicht zu den Anforderungen, Übernahme zu teuer | Neuschreibung des Bereichs bewerten | Vergleich umfasst Daten, Übergang und Betrieb |
Wählen Sie vor der Finanzierung einer vollständigen Übernahme einen begrenzten Pilot: etwa die Buchungsbestätigung zuverlässig machen und eine echte Änderung an ihrer Regel liefern. Schätzen Sie Verständnis, Risikoreduktion, Refactoring und Migration getrennt. Halten Sie Unbekanntes fest und setzen Sie einen Zeitpunkt zur Neubewertung.
Verfolgen Sie die Zeit für diese Änderung, Regressionen, Review-Aufwand und die Fähigkeit des Teams, Fehler zu diagnostizieren. Ein Repository mit mehr Tests und Dokumenten, das sich weiterhin nicht sicher ändern lässt, hat das Ziel noch nicht erreicht.
KI nach der Übernahme weiter nutzen
Agenten bleiben nützlich, um Abhängigkeiten zu kartieren, Grenzfälle vorzuschlagen und wiederholte Transformationen vorzubereiten. Fordern Sie präzise Dateiverweise, explizite Annahmen und Änderungen, die klein genug für ein Review sind.
Erwartete Testergebnisse müssen aus validierten Regeln oder beobachtetem, verstandenem Verhalten stammen. Implementierung und Bewertung aus derselben Annahme erzeugen zu lassen, kann denselben Fehler einfach zweimal reproduzieren.
Das erste Ziel der Übernahme ist konkret: Eine weitere Person im Team kann eine Geschäftsfähigkeit erklären, ändern, testen und bereitstellen, ohne die ganze Anwendung neu zu entdecken. Die fünf Bereiche dienen dieser Autonomie.
Um eine Übernahme mit Appik Studio vorzubereiten, zeigen Sie uns den Ablauf, der Sie blockiert, und die nächste erwartete Änderung. Wir können die Analyse anhand dieser Änderung, der verbundenen Risiken und der erhaltenswerten Teile des Produkts konzipieren.
Quellen und Referenzen
- DORA – State of AI-assisted Software Development 2025
- Michael Feathers – Charakterisierungstests
- Martin Fowler – gemeinsame Sprache und Domain-Driven Design
- John Ousterhout und Robert C. Martin – Zerlegung und Komplexität von Modulen
- Michael Nygard – Architekturentscheide dokumentieren
- jscodeshift – Code-Transformationen für JavaScript und TypeScript
- Danilo Sato – Parallel Change, erweitern / migrieren / zurückbauen
- Martin Fowler – schrittweise Modernisierung mit Strangler Fig
