Refaktoryzacja na Dużą Skalę z Terminala
Odkładasz tę refaktoryzację od sześciu miesięcy. Katalog utils ma 47 plików. Połowa bazy kodu używa callbacks, podczas gdy druga połowa używa async/await. Są trzy różne sposoby obsługi błędów. Twój team lead w końcu powiedział “musimy to posprzątać przed następnym pushem funkcji”, a ty wyciągnąłeś krótszą zapałkę.
Ręczna refaktoryzacja na dużą skalę jest żmudna i podatna na błędy. Zmieniasz nazwę funkcji, pomijasz jedno miejsce wywołania, a raport o błędzie przybywa o 15:00 w piątek. Claude Code zmienia to równanie. Czyta całą twoją bazę kodu, rozumie graf zależności i stosuje zmiany systematycznie w setkach plików. W połączeniu z wzorcami fan-out dla równoległego wykonywania i hookami do automatycznej weryfikacji, refaktoryzacja na dużą skalę staje się zadaniem weekendowym zamiast miesięcznego maratonu.
Co Wyniesiesz z Tej Lekcji
Dział zatytułowany „Co Wyniesiesz z Tej Lekcji”- Przepływ pracy dla bezpiecznej refaktoryzacji na dużą skalę z automatyczną weryfikacją testów
- Wzorce fan-out używające trybu headless dla transformacji całej bazy kodu
- Prompty dla typowych zadań refaktoryzacyjnych: zmiany nazw, migracje wzorców, ekstrakcja modułów
- Podejście strangler fig dla przyrostowego zastępowania starych wzorców
Bezpieczny Przepływ Pracy Refaktoryzacyjnej
Dział zatytułowany „Bezpieczny Przepływ Pracy Refaktoryzacyjnej”Duża refaktoryzacja zawodzi, gdy zmieniasz wszystko naraz, psujesz testy w sposób, którego nie rozumiesz, i spędzasz więcej czasu na debugowaniu refaktoryzacji niż spędziłeś na samej refaktoryzacji. Bezpieczne podejście jest przyrostowe: jeden wzorzec na raz, weryfikowany na każdym kroku.
-
Ustanów siatkę bezpieczeństwa
Przed zmianą jakiegokolwiek kodu upewnij się, że testy przechodzą i masz czysty stan git.
Uruchom pełny zestaw testów i potwierdź, że wszystko przechodzi.Następnie uruchom linter i type checker. Jeśli coś jest już zepsute,napraw to przed rozpoczęciem refaktoryzacji. Potrzebuję czystejlinii bazowej do refaktoryzacji. -
Przeanalizuj, co wymaga zmiany
-
Refaktoryzuj jedną partię na raz
Zacznij od partii 1: funkcje użytkowe w src/lib/.Dla każdego pliku:1. Wykonaj zmianę2. Zaktualizuj wszystkich wywołujących zmienionego kodu3. Uruchom testy dla dotkniętych modułówPokaż mi output testów po każdym pliku. Jeśli test nie przejdzie,napraw go przed przejściem do następnego pliku. -
Commituj każdą partię niezależnie
Wszystkie testy przechodzą dla partii 1. Commituj z wiadomością:"Migruj narzędzia src/lib/ z callbacks do async/await" -
Powtórz dla następnej partii
Kontynuuj, aż wszystkie partie będą ukończone. Każda partia jest commitowana niezależnie, więc możesz wykonać bisect, jeśli coś się później zepsuje.
Refaktoryzacja Fan-Out z Trybem Headless
Dział zatytułowany „Refaktoryzacja Fan-Out z Trybem Headless”Dla naprawdę dużych zmian — zmiany nazwy typu w 200 plikach, aktualizacji ścieżek importu po restrukturyzacji katalogów, lub migracji przestarzałego API — tryb headless pozwala równoległe wykonywanie pracy.
# Znajdź wszystkie pliki używające starego wzorcagrep -rl "oldFunctionName" src/ | while read file; do claude -p "W $file zmień nazwy wszystkich wystąpień oldFunctionName na newFunctionName. Zaktualizuj wszelkie powiązane nazwy zmiennych i komentarze. Nie zmieniaj logiki, tylko nazw." &donewait
# Uruchom testy do weryfikacjinpm testDla bardziej złożonych transformacji:
Używanie sub-agents do równoległej refaktoryzacji
Dział zatytułowany „Używanie sub-agents do równoległej refaktoryzacji”Wewnątrz sesji interaktywnej sub-agents mogą obsługiwać różne części refaktoryzacji jednocześnie:
Użyj sub-agents do refaktoryzacji tych trzech obszarów równolegle:
1. Migruj wszystkie pliki w src/services/ ze starego wzorca obsługi błędów do nowego wzorca AppError
2. Migruj wszystkie pliki w src/routes/ z express callbacks do async route handlers
3. Zaktualizuj wszystkie pliki w src/middleware/, aby używały nowego loggera zamiast console.log
Każdy sub-agent powinien uruchomić odpowiednie testy po wykonaniuzmian. Raportuj z wynikami.Typowe Wzorce Refaktoryzacyjne
Dział zatytułowany „Typowe Wzorce Refaktoryzacyjne”Zmiana nazwy w całej bazie kodu
Dział zatytułowany „Zmiana nazwy w całej bazie kodu”Zmień nazwę pola modelu User "fname" na "firstName" wszędzie:1. Zaktualizuj migrację bazy danych2. Zaktualizuj schemat Prisma/Drizzle3. Zaktualizuj wszystkie pliki serwisów odwołujące się do pola4. Zaktualizuj wszystkie kształty odpowiedzi API5. Zaktualizuj wszystkie pliki testowe6. Zaktualizuj wszystkie komponenty frontendu wyświetlające pole
Szukaj zarówno "fname", jak i "user.fname" i "user['fname']",aby złapać wszystkie wzorce dostępu. Uruchom pełny zestaw testówpo wszystkich zmianach.Ekstrakcja modułu z monolitu
Dział zatytułowany „Ekstrakcja modułu z monolitu”Logika uwierzytelniania jest rozproszona w sześciu plikach. Wyodrębnijją do samodzielnego katalogu src/modules/auth/:
1. Najpierw zidentyfikuj każdą funkcję, typ i stałą związaną z auth w całej bazie kodu2. Stwórz nową strukturę katalogów: - src/modules/auth/index.ts (publiczne API) - src/modules/auth/service.ts - src/modules/auth/middleware.ts - src/modules/auth/types.ts - src/modules/auth/constants.ts3. Przenieś kod, aktualizując wszystkie importy w bazie kodu4. Upewnij się, że publiczne API modułu jest wyraźne -- eksportuj tylko to, czego zewnętrzny kod faktycznie używa
Uruchom testy po każdym przeniesieniu, aby natychmiast złapać zepsute importy.Konwersja JavaScript na TypeScript
Dział zatytułowany „Konwersja JavaScript na TypeScript”Konwertuj src/legacy/ z JavaScript na TypeScript przyrostowo.Zacznij od plików liściastych (bez zależności od innych plików legacy),następnie pracuj do wewnątrz.
Dla każdego pliku:1. Zmień nazwę .js na .ts2. Dodaj adnotacje typów dla wszystkich parametrów i zwrotów funkcji3. Zastąp any właściwymi typami4. Dodaj interfejsy dla kształtów obiektów5. Napraw wszelkie błędy typów znalezione przez kompilator
Nie zmieniaj żadnej logiki. To jest migracja tylko typów.Uruchom tsc --noEmit po każdym pliku, aby natychmiast złapać błędy typów.Migracja użycia przestarzałego API
Dział zatytułowany „Migracja użycia przestarzałego API”Nasza zależność @acme/sdk właśnie wydała v3, która deprecjonujemetodę query() na rzecz execute(). Przewodnik migracji mówi:- query(sql) staje się execute({ sql })- query(sql, params) staje się execute({ sql, params })- Typ zwracany zmienił się z rows[] na { rows, metadata }
Znajdź każdy plik, który importuje z @acme/sdk i używa query().Zastosuj migrację. Zaktualizuj obsługę typu zwracanego.Uruchom testy po każdym pliku.Podejście Strangler Fig
Dział zatytułowany „Podejście Strangler Fig”Dla systemów legacy, gdzie nie możesz refaktoryzować wszystkiego na raz, użyj wzorca strangler fig: zbuduj nową wersję obok starej, stopniowo kieruj ruch do niej i usuń stary kod, gdy wszystko zostanie zmigrowane.
Musimy zastąpić naszą własną walidację Zod.Obecna walidacja jest rozproszona w ponad 30 plikach używającychwłasnych funkcji validate().
Faza 1 (ten PR):- Stwórz schematy Zod, które pasują do obecnych reguł walidacji- Dodaj wrapper kompatybilności, który uruchamia zarówno starą, jak i nową walidację i loguje rozbieżności- Wdróż i monitoruj niedopasowania
Faza 2 (następny PR):- Przełącz na Zod jako główny walidator- Zachowaj stary kod jako fallback za feature flag
Faza 3 (ostatni PR):- Usuń stary kod walidacji i feature flag- Usuń wrapper kompatybilności
Zacznij od Fazy 1. Przeczytaj trzy istniejące funkcje validate(),aby zrozumieć obecne reguły, następnie stwórz równoważne schematy Zod.Weryfikacja Refaktoryzacji za Pomocą Hooków
Dział zatytułowany „Weryfikacja Refaktoryzacji za Pomocą Hooków”Skonfiguruj hooki, które uruchamiają się po każdej edycji, aby natychmiast złapać problemy:
{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "command": "npx tsc --noEmit 2>&1 | head -20" } ] }}Dla refaktoryzacji dotyczącej wielu plików szersze sprawdzenie po każdej edycji zapobiega kaskadowym błędom:
Po każdym zmienionym pliku uruchom:1. npx tsc --noEmit (złap błędy typów natychmiast)2. npm test -- --run --reporter=dot (szybkie uruchomienie testów)
Jeśli któryś nie przejdzie, zatrzymaj się i napraw przed przejściem do następnego pliku.Nie akumuluj zepsutych plików.Pomiar Wpływu Refaktoryzacji
Dział zatytułowany „Pomiar Wpływu Refaktoryzacji”Po zakończeniu refaktoryzacji skwantyfikuj, co się poprawiło:
Porównaj bazę kodu przed i po tej refaktoryzacji:
1. Uruchom linter i porównaj liczby ostrzeżeń2. Uruchom type checker i porównaj liczby błędów3. Uruchom zestaw testów i porównaj pass/fail/czas trwania4. Policz liczbę plików, funkcji i linii kodu5. Zmierz złożoność cyklomatyczną dla zrefaktoryzowanych modułów
Pokaż mi podsumowanie przed/po, abym mógł je uwzględnić w opisie PR.Kiedy To Się Psuje
Dział zatytułowany „Kiedy To Się Psuje”Refaktoryzacja psuje test, którego się nie spodziewałeś. Zmiana miała ukrytą zależność. Wycofaj się do ostatniego commita, zbadaj zależność i zaktualizuj plan, aby ją uwzględnić. Dlatego commitowanie po każdej partii ma znaczenie — wycofania są czyste.
Zmiana nazwy pominęła niektóre miejsca wywołań. Wyszukiwanie Claude pominęło dynamiczne wzorce dostępu jak obj[fieldName] lub interpolację stringów. Po zmianie nazwy uruchom szersze wyszukiwanie: “Szukaj zarówno starej nazwy, jak i jakiegokolwiek stringa zawierającego starą nazwę. Sprawdź pliki konfiguracyjne, zapytania SQL i stringi szablonów.”
Refaktoryzacja jest zbyt duża na jedną sesję. Użyj trybu headless do części mechanicznych i zachowaj sesję interaktywną dla złożonych transformacji. Lub podziel refaktoryzację na wiele PR: “Daj mi plan, który dzieli tę refaktoryzację na trzy PR, każdy niezależnie wdrażalny i możliwy do przeglądu.”
Błędy typów kaskadują po zmianie. Zmieniłeś typ, który jest używany wszędzie. Zacznij od definicji typu i pracuj na zewnątrz: “Napraw błędy typów zaczynając od plików najbliższych zmienionemu typowi, następnie przenieś się do plików, które zależą od tych plików. Pokaż mi licznik błędów po każdym pliku.”
Zespół nadal merguje kod do plików, które refaktoryzujesz. Koordynuj z zespołem. Dla dużych refaktoryzacji rozważ krótkie zamrożenie kodu na dotkniętych plikach, lub użyj git worktrees, aby móc często rebase’ować bez utraty postępu.
Co Dalej
Dział zatytułowany „Co Dalej”Z czystym, dobrze zorganizowanym kodem i kompletnymi testami jesteś w silnej pozycji do generowania dokumentacji, która pozostaje aktualna z bazą kodu.