Legacy-Codebasen sind der Alltag der meisten Entwicklerteams. Callback-Pyramiden aus dem Jahr 2015, ungetyptes JavaScript mit 10.000 Zeilen, Class-Components die noch vor React Hooks entstanden sind — wer kennt das nicht? Claude Code verändert grundlegend, wie Teams solche Modernisierungsprojekte angehen können: nicht als großes Big-Bang-Rewrite, sondern als sicherer, schrittweiser Prozess mit KI als Co-Pilot.
Dieser Leitfaden zeigt konkrete Refactoring-Strategien für die häufigsten Legacy-Muster: JavaScript → TypeScript, Callback-Hell → async/await, React-Klassen → Hooks, rohe SQL-Abfragen → ORM und Monolith → modulare Architektur. Für jedes Muster gibt es einen Claude Code Prompt sowie realistische Before/After-Beispiele.
📋 Inhalt
- Refactoring-Strategie: Sicher modernisieren ohne Regressionen
- JavaScript → TypeScript: Typen Schritt für Schritt einführen
- Callbacks → async/await: Callback-Hell flach machen
- Klassen → React Hooks: Class Components modernisieren
- Rohe SQL → ORM: Datenbanklogik sicher migrieren
- Monolith → Module: Große Dateien aufteilen
1. Refactoring-Strategie: Sicher modernisieren ohne Regressionen
Das größte Risiko beim Refactoring ist nicht mangelndes Wissen — es sind fehlende Sicherheitsnetze. Ohne Tests, ohne strukturiertes Vorgehen und ohne klare Rollback-Strategie endet jede Modernisierungsinitiative in einem "es hat vorher irgendwie funktioniert"-Fiasko.
Das Refactoring-Sicherheitsnetz
- Tests zuerst: Charakterisierungstests schreiben die das Ist-Verhalten festhalten — noch bevor eine einzige Zeile geändert wird
- Kleine Schritte: Maximal eine Transformation pro Commit. Nie Umbenennen + Logik ändern in einem Schritt.
- git bisect als Werkzeug: Bei Regressionen schnell auf den verursachenden Commit eingrenzen
- Strangler Fig Pattern: Neues Modul parallel zum alten aufbauen, Traffic schrittweise umleiten, altes Modul erst löschen wenn neues stabil ist
- Feature Flags: Refactored Code hinter Flag — bei Problemen in Sekunden zurückschalten
"Analysiere diese Datei und erstelle Charakterisierungstests die das aktuelle Verhalten aller exportierten Funktionen dokumentieren. Fokus auf Edge Cases und Fehlerfälle. Nutze Jest/Vitest Syntax. Ziel: ein Sicherheitsnetz, das Regressionen sofort sichtbar macht."
Claude Code ist dabei besonders wertvoll in der Analysephase: Es kann eine Legacy-Datei lesen, alle Abhängigkeiten und Seiteneffekte kartieren und dann gezielt Tests für die riskantesten Stellen generieren — ohne dass der Entwickler jede Code-Zeile im Kopf haben muss.
Der Refactoring-Workflow mit Claude Code
-
1Analyse: Claude Code liest die Legacy-Datei und listet alle Code Smells, fehlenden Typen, unsicheren Muster und veralteten APIs
-
2Test-Generierung: Charakterisierungstests werden erzeugt, die das aktuelle Verhalten einfrieren
-
3Schrittweises Refactoring: Eine Transformation nach der anderen, nach jedem Schritt Tests ausführen
-
4Review: Claude Code erklärt jeden Änderungsschritt, damit das Team versteht was und warum geändert wurde
-
5Dokumentation: Automatische JSDoc/TSDoc-Kommentare für refactored Code generieren lassen
Starte jede Refactoring-Session mit: "Lies die Datei X und erstelle einen Refactoring-Plan in 5 Schritten. Gib nach jedem Schritt an, welche Tests ich ausführen soll." So bleibt Claude Code fokussiert und du behältst den Überblick.
2. JavaScript → TypeScript: Typen Schritt für Schritt einführen
Die Migration von JavaScript zu TypeScript ist eine der häufigsten Modernisierungsaufgaben. Das Ziel ist nicht, alles auf einmal mit strict: true zu erschlagen — sondern inkrementell vorzugehen und dabei maximalen Wert mit minimalem Risiko zu erzielen.
JS → TS Migrations-Strategie
- Stufe 1:
allowJs: true+checkJs: true— TypeScript prüft JS ohne Migration - Stufe 2: Dateien einzeln zu
.tsumbenennen,anyals temporären Platzhalter nutzen - Stufe 3:
anyschrittweise durch echte Typen ersetzen, von Leaf-Modulen nach innen arbeiten - Stufe 4:
strict: trueaktivieren und verbleibende Fehler systematisch beheben - Stufe 5: Utility Types (
Partial,Required,Pick) für DRY-Typdefinitionen einsetzen
"Migriere diese JavaScript-Datei zu TypeScript. Inferiere Typen aus der Verwendung wo möglich, nutze JSDoc-Annotationen als Hinweise. Vermeide any vollständig. Erstelle separate Interface-Definitionen für alle Objekte die mehr als 3 Properties haben. Erkläre deine Typ-Entscheidungen in Inline-Kommentaren."
JSDoc → TypeScript: Automatische Inferenz nutzen
Viele ältere Codebasen haben JSDoc-Kommentare als informelle Typdokumentation. Claude Code kann diese als Ausgangspunkt nutzen und echte TypeScript-Typen daraus ableiten.
Niemals as any als permanente Lösung akzeptieren. Claude Code kann angewiesen werden: "Markiere jedes any mit einem TODO-Kommentar und schlage den korrekten Typ vor." So bleiben keine stillen Typlöcher im Code.
3. Callbacks → async/await: Callback-Hell flach machen
Callback-Pyramiden sind eines der sichtbarsten Zeichen für JavaScript-Altcode. Drei oder vier Ebenen tief verschachtelter Callbacks machen Code schwer lesbar, schwer testbar und fehleranfällig. async/await ist die moderne Antwort — und Claude Code kann Callback-Ketten systematisch transformieren.
Callback → Promise → async/await
- Schritt 1: Callback-basierte Funktionen mit
util.promisifyoder manuell in Promises konvertieren - Schritt 2: Promise-Ketten (
.then().then()) mit async/await flach machen - Schritt 3:
Promise.all()für parallele Operationen einsetzen — keine unnötigen sequenziellen Awaits - Schritt 4: Error-Handling mit try/catch zentralisieren
- Schritt 5: AbortController für abbrechbare asynchrone Operationen hinzufügen
"Transformiere diese Callback-basierten Funktionen zu async/await. Identifiziere welche Operationen parallel laufen können (Promise.all) und welche sequenziell sein müssen. Füge typsicheres Error-Handling mit try/catch hinzu. Behalte die gleiche Schnittstelle nach außen."
Promise.allSettled für fehlertolerante Parallelität
"Füge AbortController-Support zu dieser async Funktion hinzu. Der Controller soll automatisch nach [X] Sekunden abbrechen und bei Component-Unmount in React gecancelt werden können."
4. Klassen → React Hooks: Class Components modernisieren
React Class Components sind funktional noch valide — aber im modernen React-Ökosystem ein Auslaufmodell. Hooks sind leichter testbar, besser composebar und brauchen weniger Boilerplate. Claude Code kann Class Components systematisch transformieren und dabei alle Lifecycle-Methoden korrekt abbilden.
Class → Function Component Mapping
| Klassen-Muster | Hook-Äquivalent |
|---|---|
this.state | useState() |
componentDidMount | useEffect([], []) |
componentDidUpdate | useEffect([deps]) |
componentWillUnmount | useEffect Cleanup-Funktion |
shouldComponentUpdate | React.memo() |
| HOC-Pattern | Custom Hook |
this.forceUpdate() | useReducer |
"Konvertiere diese React Class Component zu einer Function Component mit Hooks. Bilde alle Lifecycle-Methoden korrekt auf useEffect ab. Extrahiere Geschäftslogik in einen Custom Hook use[ComponentName]. Behalte Props-Interface identisch. Füge React.memo hinzu wo sinnvoll."
HOCs → Custom Hooks
Higher Order Components (HOCs) waren das Composability-Muster vor Hooks. Custom Hooks sind lesbarer, vermeiden Props-Drilling und können ohne Wrapper-Hölle kombiniert werden.
5. Rohe SQL → ORM: Datenbanklogik sicher migrieren
Raw-SQL-Strings im Anwendungscode sind ein Wartungsproblem: keine Typsicherheit, manuelle Sanitisierung, keine einfache Migration bei Schema-Änderungen. Moderne ORMs wie Prisma oder Drizzle ORM lösen diese Probleme — und Claude Code kann die Migration systematisch durchführen.
ORM-Migrations-Checkliste
- Schema analysieren: Claude Code liest alle SQL-Queries und erstellt daraus ein Prisma/Drizzle-Schema
- N+1-Probleme erkennen: Schleifen mit einzelnen Queries werden zu Batch-Selects mit
include - Transaktionen: Mehrere zusammengehörende Queries werden in
prisma.$transaction()gewickelt - Performance-Check: ORM-Queries gegen raw-SQL-Explain-Plan vergleichen
- Migration-Files:
prisma migrategeneriert typsichere Migrationsdateien
"Analysiere alle SQL-Queries in dieser Datei. Erstelle ein vollständiges Prisma-Schema für die verwendeten Tabellen. Konvertiere dann jede Query in die entsprechende Prisma-Client-API. Identifiziere N+1-Probleme und löse sie mit include oder select. Wickle zusammengehörende Mutations in Transaktionen ein."
Transaktionen mit Prisma
Drizzle ist SQL-first und erzeugt typsichere Queries die nah an raw SQL bleiben. Claude Code Prompt: "Erstelle ein Drizzle-Schema für diese SQL-Tabellen und konvertiere alle Queries. Behalte den SQL-ähnlichen Stil von Drizzle."
6. Monolith → Module: Große Dateien aufteilen
Eine 3.000-Zeilen-Datei die alles macht — API-Calls, Formatierung, Validierung, State-Management — ist ein klassisches Zeichen für organisch gewachsenen Code. Das Aufteilen in Module verbessert Testbarkeit, Wiederverwendbarkeit und die Zusammenarbeit im Team dramatisch.
Modularisierungs-Strategie
- Responsibility-Mapping: Claude Code analysiert die Datei und erstellt eine Karte aller Verantwortlichkeiten
- Dependency-Graph: Interne Abhängigkeiten werden sichtbar gemacht bevor etwas verschoben wird
- Barrel-Exports:
index.tsre-exportiert alles — bestehende Imports bleiben unverändert - Dependency-Inversion: Module kennen keine Implementierungsdetails, nur Interfaces
- Feature-Sliced Design: Vertikale Slices statt horizontaler Schichten — jedes Feature bekommt sein eigenes Verzeichnis
"Analysiere diese 2000-Zeilen-Datei. Erstelle eine Karte aller Verantwortlichkeiten und internen Abhängigkeiten. Schlage eine Verzeichnisstruktur vor die Single-Responsibility und Feature-Kohäsion maximiert. Erstelle dann für jedes Modul eine separate Datei mit einem zentralen index.ts der die öffentliche API re-exportiert."
Dependency-Inversion mit Interfaces
Feature-Sliced Design: Vertikal statt Horizontal
Statt Code nach technischen Schichten zu organisieren (alle Services zusammen, alle Models zusammen) gruppiert Feature-Sliced Design alles nach Business-Domänen. Das Ergebnis: ein Feature lässt sich als vollständige Einheit verstehen und ändern.
Feature-Sliced Verzeichnisstruktur
"Erstelle für jedes Unterverzeichnis eine index.ts die alle öffentlichen Exporte re-exportiert. Erstelle dann eine Root-index.ts die alle Feature-Barrel-Exporte zusammenführt. Alle bestehenden Imports sollen ohne Änderung weiterhin funktionieren."
Fazit: Refactoring mit Claude Code — was wirklich funktioniert
Claude Code ist kein Zauberstab der Legacy-Code auf Knopfdruck modernisiert — aber als methodisch eingesetzter Refactoring-Partner ist es transformativ. Die entscheidenden Learnings aus der Praxis:
- Tests zuerst, immer. Ohne Charakterisierungstests ist jedes Refactoring ein Glücksspiel. Claude Code kann die Tests generieren — aber der Entwickler muss darauf bestehen, sie auch auszuführen.
- Kleine Schritte, häufige Commits. Nie mehr als eine Transformation pro Commit.
git bisectfunktioniert nur wenn die Historie sauber ist. - Prompts sind Specs. Je präziser der Prompt, desto besser das Ergebnis. "Migriere zu TypeScript" ist zu vage — "Migriere zu TypeScript strict mode, vermeide any, erstelle Interfaces für alle Objekte mit mehr als 3 Properties" gibt Claude Code die nötige Struktur.
- Parallelismus erkennen. Claude Code findet sequenzielle Awaits die eigentlich parallel laufen könnten — ein Performance-Gewinn der bei manuellem Refactoring oft übersehen wird.
- Nicht überrefactorn. Das Ziel ist nicht der perfekte Code — es ist sicherer, wartbarer Code. Perfekt ist der Feind von gut.
Legacy-Code modernisieren mit KI-Unterstützung
Teste Claude Code 14 Tage kostenlos und erlebe wie dein Team Refactoring-Projekte 3-5× schneller und sicherer abschließt.
Kostenlos starten — 14 Tage Trial