ix
ix

informatix

EN version Porozmawiajmy o projekcie
Strona główna / Blog / Refaktoryzacja legacy code — przewodnik z praktyki [2026]
• 8 min czytania •

Refaktoryzacja legacy code — przewodnik z praktyki [2026]

Refaktoryzacja legacy code to poprawa struktury starego kodu bez zmiany jego zachowania — i bez zatrzymywania produkcji. Kolejność, techniki i narzędzia, które działają w starym PHP.

Refaktoryzacja legacy code to kontrolowana poprawa struktury starego kodu bez zmiany jego zachowania — bez przepisywania systemu od zera i bez zatrzymywania produkcji. Dobrze przeprowadzona refaktoryzacja obniża koszt każdej kolejnej zmiany, skraca czas wdrożeń i zmniejsza liczbę błędów. Ten przewodnik pokazuje, jak ją zaplanować, jakie techniki działają w starym kodzie PHP i kiedy refaktoryzacja przestaje się opłacać.

Najważniejsze: Refaktoryzacja nie zmienia tego, co system robi — zmienia tylko to, jak jest zbudowany. Zasada bezpieczeństwa jest jedna: najpierw testy zabezpieczające (charakterystyczne), potem refaktoryzacja, na końcu wdrożenie modułami. Bez testów refaktoryzacja to nie modernizacja, a hazard.

Czym jest refaktoryzacja i czym nie jest

Refaktoryzacja to zmiana wewnętrznej struktury kodu przy zachowaniu identycznego zachowania zewnętrznego. Martin Fowler definiuje ją jako „proces poprawy projektu istniejącego kodu bez zmiany jego zachowania" — i ten warunek jest istotą, nie ozdobnikiem. Jeśli po zmianie system zachowuje się inaczej (nawet „lepiej"), to nie jest refaktoryzacja, lecz zmiana funkcjonalna, która wymaga osobnego procesu i osobnych testów.

Refaktoryzacja to nie jest

  • przepisanie modułu od zera — to wymiana implementacji, opisana szerzej w artykule refaktoryzacja czy przepisanie od zera,
  • optymalizacja wydajności — refaktoryzacja może ją ułatwić, ale sama nie goni za milisekundami,
  • kosmetyka formatowania — porządki w stylu kodu robi się automatem, nie projektem modernizacji,
  • dodawanie funkcji — nowe zachowanie wymaga nowych testów i zwykle innego cyklu wdrożenia.

Refaktoryzacja to inwestycja w koszt przyszłych zmian. Każdy moduł zrefaktoryzowany do czytelnej struktury sprawia, że kolejne dwadzieścia zmian w tym module będzie tańszych, szybszych i bezpieczniejszych.

Kiedy refaktoryzować, a kiedy tylko łatać

Nie każdy fragment starego kodu zasługuje na refaktoryzację — i to jest pierwsza decyzja, którą warto podjąć świadomie. W projektach, które przejmuję, dzielę kod na cztery kategorie:

  • kod krytyczny i często zmieniany — refaktoryzuj pierwszy, bo tu każda zmiana boli najbardziej,
  • kod krytyczny, ale stabilny — zabezpiecz testami i zostaw; dotykaj tylko przy okazji realnej potrzeby,
  • kod niekrytyczny i często zmieniany — refaktoryzuj przy okazji zmian funkcjonalnych,
  • kod martwy — usuń, nie refaktoryzuj. Porządkowanie nieużywanego kodu to najczęstsza pułapka modernizacji.

Punkt wyjścia to zawsze rozpoznanie systemu — mapa zależności, lista modułów krytycznych i ich historii zmian. Bez tego refaktoryzacja zamienia się w porządkowanie losowych plików. Jak wygląda taki przegląd od strony praktycznej, opisuję w przewodniku o audycie kodu legacy, a cały plan modernizacji — od audytu po CI/CD — w artykule o modernizacji legacy code krok po kroku.

Testy zabezpieczające — warunek konieczny

Refaktoryzacja bez testów jest niebezpieczna z prostego powodu: jeśli nie wiesz, co system robi teraz, nie możesz stwierdzić, czy po zmianie robi to samo. W starym kodzie rzadko są testy jednostkowe, ale to nie znaczy, że jesteś bez narzędzi.

Sprawdzone podejście to testy charakterystyczne — opisujesz testami bieżące zachowanie systemu, także to nieidealne, i traktujesz je jako kontrakt. Technikę i konkretne przykłady w PHPUnit opisuję w artykule o testach charakterystycznych. Uzupełnieniem są testy end-to-end na ścieżkach krytycznych: logowanie, zamówienie, płatność, faktura. Te kilka testów daje więcej bezpieczeństwa niż tydzień analizy.

Dopiero gdy moduł ma siatkę bezpieczeństwa, można go tkwić. Kolejność jest nienegocjowalna — i to jest różnica między refaktoryzacją a improwizacją.

Techniki refaktoryzacji, które działają w starym kodzie

W legacy kodzie sprawdzają się techniki o małym zasięgu — każda z nich jest odwracalna i weryfikowalna przez testy

  • wydzielanie funkcji i metod (extract method) — najprostsza i najskuteczniejsza technika; rozbija długie procedury na kroki o nazwach opisujących intencję,
  • wprowadzenie warstwy pośredniej (branch by abstraction) — między starą i nową implementację wstawiasz interfejs, co pozwala podmieniać implementacje bez zmian w miejscach wywołań,
  • odwrócenie zależności — zamiast wywołań globalnych funkcji i statycznych klas wprowadzasz wstrzykiwanie zależności, co czyni kod testowalnym,
  • usuwanie duplikacji — powtarzalne bloki zamieniasz na wspólne funkcje; w starym kodzie duplikacja jest głównym źródłem „naprawiłem w jednym miejscu, zepsuło się w trzech",
  • porządki w nazewnictwie — zmienne $data2, $tmp i funkcje processStuff() kosztują więcej czasu niż jakakolwiek architektura,
  • izolacja efektów ubocznych — wydzielenie kodu odpowiedzialnego za zapisy do bazy, wysyłkę maili i wywołania API od logiki biznesowej.

Dla dużych monolitów techniką nadrzędną jest wzorzec Strangler Fig — nowy kod wyrasta wokół starego i przejmuje jego funkcje moduł po module. Opisuję go w artykule o wzorcu Strangler Fig.

Refaktoryzacja wspierana narzędziami

Ręczna refaktoryzacja dużego systemu to miesiące pracy. Automatyzacja zmienia ekonomię całego procesu

  • Rector wykonuje masowe refaktoryzacje i aktualizacje składni PHP — zmiany, które ręcznie zajęłyby kwartał, potrafi przygotować jako pull request w godzinę,
  • PHPStan i Psalm wychwytują błędy typów i martwy kod przed uruchomieniem; w legacy zaczynasz od najłagodniejszego poziomu i podnosisz poprzeczkę moduł po module,
  • PHPUnit i Pest utrwalają zachowanie modułu przed zmianami,
  • IDE (PhpStorm, VS Code) z analizą statyczną bezpiecznie wykonuje zmiany nazw, sygnatur i przenoszenie kodu,
  • Laravel Shift automatyzuje aktualizacje frameworka między wersjami, jeśli system korzysta z Laravel.

Zestaw startowy jest darmowy lub tani: PHPStan, Rector i PHPUnit to open source. Kolejność wdrożenia opisuję w pillarze o modernizacji legacy code.

Proces refaktoryzacji krok po kroku

Sprawdzony cykl dla jednego modułu wygląda tak

  1. Wybierz moduł — krytyczny dla biznesu i często zmieniany, ale nie najtrudniejszy w systemie. Pierwszy moduł ma dać zespół i proces, nie medal.
  2. Zabezpiecz testami — charakterystyczne na bieżące zachowanie, end-to-end na ścieżkę użytkownika, jeśli moduł jej dotyczy.
  3. Zrefaktoryzuj w małych krokach — każdy krok kończy się uruchomieniem testów. Commit po każdym zielonym kroku.
  4. Wdróż na staging — niech nowa wersja „poleży" pod ruchem testowym.
  5. Wdróż na produkcję i monitoruj — błędy, wydajność, logi. Kilka dni obserwacji przed uznaniem modułu za zamknięty.
  6. Dopisz testy jednostkowe nowych, wyodrębnionych fragmentów — dług techniczny spłacasz przy okazji, nie „kiedyś".

Tempo ma znaczenie mniejsze niż rytm. Jeden moduł na sprint, wdrożony i zweryfikowany, bije trzy moduły zrefaktoryzowane „prawie na gotowo" i wdrożone razem.

Kiedy refaktoryzacja się nie opłaca

  • Uczciwa odpowiedź: czasem refaktoryzacja nie jest właściwym narzędziem.

  • Moduł jest nie do uratowania, a jego logika prosta — taniej przepisać go od zera z testami niż refaktoryzować warstwa po warstwie.

  • Kod działa i nikt go nie zmienia — każda godzina refaktoryzacji takiego modułu to koszt bez zwrotu; zostaw go z testami bezpieczeństwa i monitoringiem.

  • Zbliża się wymiana całego systemu — jeśli firma zdecydowała o migracji do nowej platformy w horyzoncie kwartału, refaktoryzacja starego kodu to praca wrzucona do kosza.

  • Brak testów i brak czasu na nie — refaktoryzacja bez zabezpieczenia to nie modernizacja; w takiej sytuacji zacznij od testów, nie od zmian struktury.

Refaktoryzacja jest narzędziem, nie celem. Celem jest system, który znów daje się rozwijać w przewidywalnym czasie i budżecie.

Najczęściej zadawane pytania

Ile trwa refaktoryzacja legacy code?

To zależy od skali i jakości testów. Refaktoryzacja pojedynczego modułu to zwykle od kilku dni do dwóch tygodni — z testami charakterystycznymi i wdrożeniem. Cały system dzieli się na moduły i refaktoryzuje etapami przez miesiące, bez zatrzymywania produkcji.

Czy refaktoryzacja wymaga zatrzymania systemu?

Nie. Refaktoryzacja modułowa polega na tym, że system działa cały czas — zmiany przechodzą przez staging i są wdrażane pojedynczo, z monitoringiem po każdym wdrożeniu. Przestój nie jest częścią procesu.

Czym różni się refaktoryzacja od przepisania od zera?

Refaktoryzacja poprawia strukturę istniejącego kodu, zachowując jego zachowanie i technologie. Przepisanie od zera buduje nowy system obok starego, z nowymi decyzjami technologicznymi — jest droższe, dłuższe i obarczone większym ryzykiem. Większość systemów potrzebuje refaktoryzacji, a nie przepisania.

Czy refaktoryzacja może zepsuć działający system?

Może, jeśli prowadzisz ją bez testów i wdrożeń modułami. Z testami charakterystycznymi, wdrożeniem na staging i monitoringiem po wdrożeniu ryzyko jest ograniczone do jednego modułu — a nie całego systemu. To dokładnie ten sam standard bezpieczeństwa, który stosuje się przy każdej innej zmianie w kodzie produkcyjnym.

Źródła i narzędzia

Darmowy PDF

Checklista wymagań do wyceny aplikacji

12 pytań kontrolnych, które warto przygotować przed rozmową z wykonawcą — szybsza wycena, mniej ukrytych kosztów.

Powiązane wpisy