Przejęcie projektu IT po innym wykonawcy - jak bezpiecznie zmienić software house?
Jak bezpiecznie przejąć projekt IT po innym wykonawcy? Sprawdź kod, dostępy, infrastrukturę, dokumentację i proces zmiany software house.
System może działać poprawnie, a mimo to każda kolejna zmiana zajmuje coraz więcej czasu. Nowa funkcjonalność wymaga ingerencji w kilka pozornie niezwiązanych modułów, niewielka poprawka powoduje regresje, a developerzy coraz częściej omijają istniejący kod zamiast go rozwijać.
W takiej sytuacji problemem nie zawsze jest brak nowych technologii ani konieczność napisania systemu od początku. Czasami potrzebna jest refaktoryzacja kodu – uporządkowanie jego wewnętrznej struktury tak, aby dalszy rozwój był bezpieczniejszy i bardziej przewidywalny.
Refaktoryzacja powinna jednak wynikać z konkretnego problemu. Nie każdy stary kod trzeba poprawiać i nie każdy fragment, który można napisać „ładniej”, warto przebudowywać.
W tym artykule wyjaśniamy, czym jest refaktoryzacja kodu, kiedy ma uzasadnienie, czym różni się od rewrite’u i modernizacji, jak wybrać obszary wymagające zmian oraz jak ocenić, czy koszt refaktoryzacji rzeczywiście się opłaca.
Refaktoryzacja kodu to zmiana jego wewnętrznej struktury bez celowej zmiany funkcjonalności widocznej dla użytkownika.
Jej celem może być między innymi uproszczenie skomplikowanej logiki, usunięcie duplikacji, lepsze rozdzielenie odpowiedzialności pomiędzy modułami, zwiększenie testowalności oraz ułatwienie kolejnych zmian w systemie.
Dobrze przeprowadzona refaktoryzacja nie polega na przepisywaniu kodu tylko dlatego, że nowy developer zrobiłby coś inaczej. Powinna rozwiązywać konkretny problem wpływający na utrzymanie, bezpieczeństwo zmian lub dalszy rozwój oprogramowania.
W praktyce refaktoryzacja jest jednym z narzędzi wykorzystywanych podczas rozwoju istniejących systemów. Może być wykonywana jako osobny etap albo stopniowo, przy okazji prac nad modułami, które wymagają kolejnych zmian.
Te pojęcia często pojawiają się w podobnym kontekście, ale nie oznaczają tego samego.
Zmienia wewnętrzną strukturę istniejącego kodu bez celowej zmiany jego funkcjonalności. Jej celem jest przede wszystkim ułatwienie utrzymania i dalszego rozwoju systemu.
Oznacza napisanie całego systemu lub wybranego modułu od początku. To znacznie większa decyzja niż refaktoryzacja i powinna wynikać z problemów, których nie da się racjonalnie rozwiązać poprzez stopniowe zmiany istniejącego rozwiązania.
Może obejmować aktualizację frameworka, wersji języka, bibliotek, infrastruktury albo zmianę sposobu wdrażania aplikacji. Refaktoryzacja może być elementem modernizacji, ale nie są to pojęcia równoznaczne.
Jej celem jest przede wszystkim poprawa szybkości działania lub wykorzystania zasobów. Czasami wymaga zmian w kodzie, ale wolna aplikacja nie oznacza automatycznie, że potrzebuje refaktoryzacji.
Dlatego przed rozpoczęciem prac warto najpierw ustalić, jaki problem rzeczywiście chcemy rozwiązać.
Refaktoryzacja ma największe uzasadnienie wtedy, gdy sposób zbudowania istniejącego kodu zaczyna realnie utrudniać dalszą pracę nad systemem.
Sygnałem może być sytuacja, w której:
Refaktoryzacja może być również jednym ze sposobów ograniczania długu technologicznego, ale nie każdy dług technologiczny trzeba usuwać natychmiast.
Największy priorytet powinny mieć te problemy, które wpływają na często rozwijane moduły, powodują błędy, zwiększają ryzyko kolejnych wdrożeń albo wyraźnie podnoszą koszt nowych zmian.
Właściwie zaplanowana refaktoryzacja może przede wszystkim:
Korzyści nie zawsze są natychmiast widoczne dla użytkownika końcowego. Refaktoryzacja ma przede wszystkim poprawić zdolność zespołu do bezpiecznego i przewidywalnego rozwijania systemu.
Dlatego jej efekt warto mierzyć nie liczbą zmienionych plików czy klas, ale tym, czy po wykonaniu prac kolejne zmiany w danym obszarze rzeczywiście stały się prostsze i mniej ryzykowne.
Refaktoryzacja może przyjmować różne formy – od prostych działań po bardziej zaawansowane techniki. Przykładowe praktyki to:
Dobór techniki powinien wynikać z konkretnego problemu w kodzie. Samo zastosowanie wzorca projektowego czy podział klasy na mniejsze elementy nie jest celem refaktoryzacji, jeżeli nie poprawia utrzymywalności lub nie zmniejsza ryzyka dalszych zmian.
Nie warto zaczynać od fragmentu tylko dlatego, że wygląda na najbardziej nieuporządkowany.
Większy priorytet powinny mieć obszary, które:
Fragment starego kodu, który działa stabilnie i od kilku lat nie wymaga modyfikacji, może być znacznie mniej istotny niż mniejszy problem w module rozwijanym każdego tygodnia.
Jeżeli nie wiadomo, gdzie rzeczywiście znajduje się źródło problemów, przed większą refaktoryzacją warto najpierw ocenić stan systemu. Szerzej opisujemy to w artykule Audyt techniczny systemu informatycznego – co sprawdzić przed dalszym rozwojem lub przejęciem aplikacji?
Koszt refaktoryzacji zależy przede wszystkim od zakresu zmian, złożoności kodu, liczby zależności oraz poziomu zabezpieczenia systemu testami.
Nie powinno się wyceniać refaktoryzacji wyłącznie na podstawie liczby linii kodu albo wieku aplikacji. Dwa podobnej wielkości moduły mogą wymagać zupełnie innego nakładu pracy.
Przy ocenie opłacalności warto zestawić koszt refaktoryzacji z kosztem pozostawienia obecnego rozwiązania.
Refaktoryzacja ma szczególne uzasadnienie, gdy problematyczny obszar:
Z kolei przebudowa stabilnego modułu, który praktycznie nie jest już rozwijany, może nie przynieść korzyści proporcjonalnych do kosztu.
Dlatego refaktoryzacji nie warto traktować jako projektu polegającego na „poprawieniu całego kodu”. Znacznie częściej lepsze rezultaty daje wybranie obszarów, w których uporządkowanie kodu będzie miało największy wpływ na dalszy development.
Możemy przeanalizować problematyczne obszary i określić, czy właściwym kierunkiem jest refaktoryzacja, modernizacja wybranych modułów czy pozostawienie obecnego rozwiązania bez zmian.
Refaktoryzacja powinna ograniczać ryzyko dalszego rozwoju systemu, a nie tworzyć nowe.
Dlatego przed rozpoczęciem większych zmian warto:
Szczególnie ryzykowne jest jednoczesne wykonywanie dużej refaktoryzacji i wielu zmian funkcjonalnych w tym samym obszarze. Im trudniej rozdzielić zmianę struktury kodu od zmiany zachowania systemu, tym trudniej później ustalić źródło ewentualnego problemu.
Dlatego w wielu istniejących systemach lepiej sprawdza się refaktoryzacja etapami niż jednorazowa przebudowa dużej części aplikacji.
Nie każdy technicznie niedoskonały kod wymaga przebudowy.
Refaktoryzacja może mieć niski priorytet, gdy:
Dobra decyzja techniczna nie polega na poprawieniu możliwie dużej liczby niedoskonałości. Polega na zmianie tych elementów, których obecna forma rzeczywiście utrudnia rozwój lub zwiększa ryzyko.
Refaktoryzacja nie powinna być celem samym w sobie. Jest narzędziem do poprawy tych obszarów istniejącego systemu, które utrudniają jego bezpieczny i przewidywalny rozwój.
Największą wartość przynosi wtedy, gdy dotyczy kodu często zmienianego, krytycznego biznesowo albo generującego powtarzalne problemy podczas kolejnych wdrożeń.
Nie oznacza też automatycznie przebudowy całego systemu. W wielu przypadkach najlepszym rozwiązaniem jest stopniowe porządkowanie konkretnych modułów równolegle z dalszym developmentem.
Jeżeli istniejący system wymaga przejęcia, modernizacji lub dalszego rozwoju przez nowy zespół, zobacz również Firma programistyczna.
Refaktoryzacja kodu to zmiana jego wewnętrznej struktury bez celowej zmiany funkcjonalności widocznej dla użytkownika. Jej celem jest przede wszystkim ułatwienie utrzymania, testowania i dalszego rozwoju systemu.
Wtedy, gdy obecna struktura kodu realnie utrudnia dalszą pracę – na przykład powoduje regresje, wymusza kolejne obejścia, utrudnia testowanie albo znacząco zwiększa koszt nowych zmian.
Co do zasady nie. Prawidłowo przeprowadzona refaktoryzacja powinna zachować dotychczasowe zachowanie systemu, zmieniając przede wszystkim sposób organizacji i implementacji kodu.
Refaktoryzacja wykorzystuje istniejący kod i stopniowo poprawia jego strukturę. Rewrite oznacza stworzenie całego systemu lub wybranego modułu od początku i jest znacznie większą ingerencją w istniejące rozwiązanie.
Nie. Największy sens ma wtedy, gdy dotyczy obszarów często rozwijanych, generujących błędy albo zwiększających koszt kolejnych zmian. Stabilnego modułu, który praktycznie nie jest już modyfikowany, nie zawsze warto przebudowywać.
Tak. W wielu systemach jest to najbezpieczniejsze podejście. Refaktoryzacja może być wykonywana stopniowo, razem z dalszym rozwojem tych modułów, które rzeczywiście wymagają uporządkowania.
Tak, szczególnie przy zmianach dotyczących kluczowych procesów systemu. Testy pomagają sprawdzić, czy po zmianie struktury kodu jego dotychczasowe zachowanie pozostało niezmienione.
Tak, może być jednym ze sposobów jego ograniczania. Nie oznacza to jednak, że każdy element długu technologicznego trzeba usuwać – priorytet powinny mieć problemy, które realnie wpływają na rozwój, stabilność lub koszt kolejnych zmian.
Ten wpis stworzył
Założyciel Webtom.pl, lider, który z pasją kształtuje przyszłość branży cyfrowej od 2005 roku. Dusza firmy, wprowadzająca w życie innowacyjne strategie, które transformują sposób, w jaki tworzymy i doświadczamy web designu i technologii internetowych. Wykorzystuje potęgę internetu do rozwoju biznesu naszych Partnerów.