Refactor czy przepisać od zera — jak podjąć tę decyzję na liczbach, a nie na przeczuciu

Rewrite kusi, bo obiecuje czystą kartę, a wycenia się go tak, jakby czysta karta była za darmo. Pokazujemy realny koszt przepisania, pięć pytań, które rozstrzygają decyzję, oraz strangler pattern jako trzecią drogę.

Zespół Mobilesoft· Engineering team· 14 września 2026· 8 min czytania

„Przepiszmy to od nowa" — najdroższe zdanie w projekcie IT

Każdy zespół pracujący dłużej niż rok na tym samym kodzie w końcu je wypowiada. Zwykle na retrospektywie, zwykle po trzecim z rzędu wydaniu, które coś zepsuło. Zdanie brzmi rozsądnie: kod jest zły, więc napiszmy dobry. Problem w tym, że to nie jest decyzja techniczna — to decyzja finansowa o zamrożeniu rozwoju produktu na kilka kwartałów i zwykle podejmuje się ją na podstawie emocji, a nie liczb.

W audytach to pytanie pada niemal zawsze: rozwijać czy przepisać. W tekście o tym, co zawiera audyt kodu źródłowego, napisaliśmy, że rewrite to niemal zawsze najgorsza odpowiedź i że jeśli ją proponujemy, musimy obronić ją liczbami. Ten tekst pokazuje te liczby oraz konkretne kryteria decyzji.

Dlaczego rewrite tak kusi

Warto nazwać mechanizm, bo dopóki jest nienazwany, wygrywa każdą dyskusję.

Czytanie kodu jest trudniejsze niż pisanie. To najstarsza obserwacja w tej branży. Cudzy kod zawsze wygląda gorzej niż własny, bo nie widać w nim intencji — widać tylko wynik. Programista czytający zagmatwaną funkcję nie widzi trzech incydentów produkcyjnych, które ją takim uczyniły. Widzi bałagan.

Nowy projekt nie ma jeszcze problemów. Greenfield to stan, w którym wszystkie decyzje są jeszcze przed nami, więc żadna nie jest jeszcze zła. To złudzenie komfortu, które znika w trzecim miesiącu — nowy system zaczyna zbierać własne kompromisy dokładnie w tym samym tempie co poprzedni.

Rewrite jest łatwiejszy do zaplanowania niż refactor. Nowy system da się narysować na slajdzie i podzielić na etapy. Stopniowa naprawa istniejącego to setki drobnych decyzji rozłożonych na miesiące, bez efektownego kamienia milowego pośrodku.

Te trzy rzeczy sprawiają, że estymacje rewrite'u są systematycznie zaniżone, a estymacje refactoru — zawyżone. Zanim porównasz obie ścieżki, załóż, że liczba przy rewrite jest optymistyczna co najmniej dwukrotnie.

Prawdziwy koszt przepisania

Kosztem nie jest napisanie nowego systemu. Kosztem jest wszystko dookoła.

Utrzymanie dwóch systemów naraz. Przez cały okres przepisywania stary system musi działać, dostawać poprawki bezpieczeństwa i reagować na wymogi zewnętrzne — zmianę w API płatności, nową wersję Androida, wymóg regulacyjny. Każda taka zmiana jest teraz robiona dwa razy. To zwykle 20–30% mocy zespołu, której nie było w pierwotnym planie.

Feature freeze i jego cena biznesowa. Przez kilka kwartałów produkt nie dostaje nowych funkcji, bo zespół odtwarza te, które już ma. Dla działu sprzedaży oznacza to konkretną odpowiedź na pytanie klienta „czy dodacie X" — brzmiącą „nie w tym roku". To najczęściej pomijana pozycja w kalkulacji, a zwykle największa.

Wiedza zaszyta w dziwnych miejscach. Ten nielogiczny warunek w module rozliczeń to zwykle nie bałagan — to obsługa przypadku klienta, który zgłosił się dwa lata temu. Nowy system odtwarza funkcje z opisu, nie z historii incydentów, więc odkrywa te przypadki ponownie, po kolei, na produkcji.

Efekt drugiego systemu. Zespół, który dostaje szansę zrobić wszystko „porządnie", ma tendencję do przeprojektowania. Nowy system dostaje warstwy abstrakcji na potrzeby, które nigdy nie wystąpią. Bywa, że kończy się bardziej skomplikowany niż ten, który zastępował.

Praktyczna reguła z naszych projektów: realny koszt rewrite'u to 2–3× pierwsza estymacja, a czas do parytetu funkcjonalnego ze starym systemem to zwykle 1,5–2× planowany. Jeśli po podstawieniu tych mnożników decyzja nadal wychodzi na korzyść przepisania — jest prawdopodobnie słuszna.

Pięć pytań, które faktycznie rozstrzygają

1. Gdzie leży problem — w kodzie czy w architekturze?

To pytanie rozstrzyga najwięcej. Brzydki kod w dobrej architekturze naprawia się przyrostowo, moduł po module, bez zatrzymywania rozwoju. Zła architektura — brak granic między modułami, logika biznesowa rozlana po UI, wszystko zależne od wszystkiego — nie da się naprawić lokalnie, bo każda zmiana dotyka całości.

Test praktyczny: czy da się wymienić jeden moduł, nie dotykając reszty? Jeśli tak, refactor. Jeśli każda zmiana wymaga dotknięcia dziesięciu plików w czterech warstwach — problem jest strukturalny i sam refactor go nie rozwiąże.

2. Czy platforma jest żywa?

Framework bez wsparcia, język w wersji po końcu życia, biblioteka kluczowa dla systemu porzucona przez autora, SDK, którego producent sprzętu już nie wydaje. Jeśli nie da się załatać podatności bezpieczeństwa, bo nie ma czego zaktualizować, dyskusja o jakości kodu jest bezprzedmiotowa. To jeden z niewielu argumentów, który sam w sobie uzasadnia przepisanie.

Uwaga na wersję łagodniejszą tego problemu: framework starszy o dwie duże wersje to zwykle nie rewrite, tylko migracja — kosztowna, ale wielokrotnie tańsza.

3. Ile kosztuje zamrożenie produktu?

Policzalne pytanie. Ile funkcji nie powstanie przez najbliższe dwa–trzy kwartały i co to znaczy dla sprzedaży, retencji lub zobowiązań wobec klientów. Jeśli produkt jest w fazie zdobywania rynku, feature freeze może być groźniejszy niż dług techniczny. Jeśli produkt jest dojrzały i stabilny — koszt zamrożenia jest niski, a rewrite staje się realną opcją.

4. Czy zespół zna domenę?

Przepisanie systemu przez ludzi, którzy nie znają reguł biznesowych, to odtwarzanie ich z kodu — czyli dokładnie ta praca, której rewrite miał uniknąć. Jeśli osoby, które budowały pierwszą wersję, są niedostępne, ryzyko rośnie skokowo, bo nie ma kogo zapytać, dlaczego dany warunek tam jest.

5. Czy istnieją testy krytycznych ścieżek?

Refactor bez siatki bezpieczeństwa jest ryzykowny, ale testy da się dopisać. Rewrite bez testów starego systemu jest gorszy: nie masz specyfikacji wykonywalnej tego, co nowy system ma robić, więc jedynym weryfikatorem parytetu są użytkownicy po wdrożeniu.

Trzecia droga: strangler pattern

Wybór rzadko jest binarny. Wzorzec duszącego figowca — nowy system wyrasta wokół starego i stopniowo przejmuje jego funkcje, aż stary przestaje być potrzebny — pozwala mieć jedno i drugie: nowoczesny kod i ciągły rozwój produktu.

W praktyce wygląda to tak:

  1. Postaw warstwę kierującą ruchem. Proxy, gateway albo routing w aplikacji, który decyduje: to żądanie idzie do starego systemu, tamto do nowego. Bez tego kroku wzorzec nie działa.
  2. Wybierz pierwszy moduł — mały i na brzegu. Nie ten najbardziej zepsuty i nie centralny. Chodzi o przećwiczenie mechanizmu, nie o efekt.
  3. Przenieś funkcję, przekieruj ruch, obserwuj. Przez jakiś czas oba systemy mogą działać równolegle na tych samych danych, z porównywaniem wyników.
  4. Powtarzaj, zaczynając od modułów o największej wartości. Po każdym kroku produkt działa i można zwolnić tempo albo zatrzymać się, jeśli priorytety się zmienią.

Największa zaleta jest organizacyjna, nie techniczna: na każdym etapie masz działający produkt i możesz przerwać. Rewrite tego nie daje — przerwany w połowie zostawia dwa niekompletne systemy i zmarnowany kwartał.

Cena też jest realna: przez cały okres migracji utrzymujesz warstwę kierującą i podwójną integrację danych. To rozwiązanie wolniejsze i mniej eleganckie od rewrite'u — za to takie, które da się przeżyć.

W projektach mobilnych ten sam mechanizm stosujemy modułowo: nowe ekrany powstają w nowej architekturze, stare pozostają, dopóki nie dotknie ich zmiana biznesowa. Więcej o tym, jak podchodzimy do porządkowania zaniedbanych aplikacji, w opisie usługi reaktywacji aplikacji.

Kiedy rewrite naprawdę jest właściwą decyzją

Są sytuacje, w których przepisanie jest jedyną uczciwą odpowiedzią:

  • Platforma martwa bez ścieżki migracji — nie ma czego aktualizować, nie ma poprawek bezpieczeństwa.
  • Brak kodu źródłowego lub możliwości zbudowania projektu. Zaskakująco częsty przypadek przy przejęciach: jest aplikacja w sklepie, nie ma repozytorium albo nie ma certyfikatu, którym ją podpisano.
  • Model biznesowy zmienił się fundamentalnie. System zaprojektowany pod jednego dużego klienta rzadko da się przerobić na wielodostępny SaaS bez przebudowy fundamentów.
  • Skala poza projekt. Architektura obliczona na tysiąc użytkowników przy stu tysiącach nie potrzebuje refactoru, tylko innego projektu.
  • System jest mały. Przy kilku tygodniach pracy cała ta kalkulacja przestaje mieć znaczenie — przepisz i nie zwołuj warsztatu.

Zwróć uwagę, że w żadnym z tych punktów nie ma sformułowania „kod jest brzydki". Brzydki kod jest argumentem za refactorem, nigdy za rewrite'em.

Jak podjąć tę decyzję odpowiedzialnie

Trzy rzeczy, które warto zrobić przed decyzją:

Zmierz, zamiast dyskutować. Czas od pomysłu do produkcji, liczba regresów na wydanie, czas onboardingu nowego developera, udział czasu na naprawy w sprincie. Bez tych liczb rozmowa jest wymianą wrażeń, a wygrywa ją najbardziej stanowcza osoba w pokoju.

Zrób próbę na jednym module. Wybierz najbardziej problematyczny fragment i spróbuj go uporządkować w dwa tygodnie. Wynik tej próby powie więcej niż miesiąc analiz: jeśli się udało — masz odpowiedź i działający moduł. Jeśli nie dało się ruszyć bez pociągnięcia całego systemu — masz twardy argument za przebudową architektury.

Poproś o niezależną ocenę. To decyzja obciążona silnym biasem po obu stronach: zespół, który pisał kod, będzie go bronił; zespół, który wchodzi na jego miejsce, będzie chciał go przepisać. Drugie oczy z zewnątrz nie mają w tym interesu — dlatego w audytach i konsultacjach traktujemy to pytanie jako osobny punkt raportu, z estymacją obu ścieżek.

Osobno warto oddzielić dług techniczny, z którym da się żyć, od tego, który realnie blokuje rozwój — o kryteriach tego podziału piszemy w tekście o tym, kiedy spłacać dług techniczny, a kiedy z nim żyć.

Podsumowanie

Rewrite jest kuszący, bo obiecuje czystą kartę, a wycenia się go tak, jakby czysta karta była za darmo. W praktyce płacisz podwójnym utrzymaniem, zamrożeniem produktu i ponownym odkrywaniem przypadków brzegowych, które stary system obsługiwał od lat.

W większości sytuacji właściwą odpowiedzią jest stopniowa wymiana — mniej efektowna, za to odwracalna na każdym etapie. Rewrite zostaw na przypadki, w których stary system naprawdę nie ma przyszłości: martwa platforma, brak źródeł, zmiana modelu biznesowego.

Jeśli stoisz przed tą decyzją i chcesz, żeby ktoś policzył obie ścieżki, zanim pieniądze pójdą w jedną z nich — napisz do nas albo wyceń projekt. Zobacz też nasze realizacje: sporo z nich zaczynało się właśnie od tego pytania.