Świetni programiści wiedzą, kiedy i jak zrefaktoryzować kod Rails
Opublikowany: 2022-03-11Refaktoryzacja na dużą skalę: Dlaczego miałbyś kiedykolwiek zrobić coś takiego?
Jeśli nie jest zepsuty, nie naprawiaj tego.
To dobrze znana fraza, ale jak wiemy, większość postępu technologicznego ludzkości dokonali ludzie, którzy postanowili naprawić to, co nie jest zepsute. Szczególnie w branży oprogramowania można by argumentować, że większość tego, co robimy, to naprawianie tego, co nie jest zepsute.
Naprawianie funkcjonalności, ulepszanie interfejsu użytkownika, poprawianie szybkości i wydajności pamięci, dodawanie funkcji: to wszystko czynności, dla których łatwo jest zobaczyć, czy są warte wykonania, a potem my, jako doświadczeni programiści Rails, opowiadamy się za lub przeciw spędzaniu na nich czasu. Istnieje jednak czynność, która w większości mieści się w szarej strefie – standardowa refaktoryzacja, a zwłaszcza refaktoryzacja kodu na dużą skalę.
Termin refaktoryzacja na dużą skalę zasługuje na wyjaśnienie. Dokładnie to, co można uznać za „dużą skalę”, będzie się różnić w zależności od przypadku, ponieważ termin jest nieco niejasny, ale uważam, że wszystko, co znacząco wpływa na więcej niż tylko kilka klas lub więcej niż tylko jeden podsystem, a jego interfejs jest „duży ”. Z drugiej strony, każda refaktoryzacja Railsów, która pozostaje ukryta za interfejsem pojedynczej klasy, byłaby zdecydowanie „mała”. Oczywiście pomiędzy nimi jest dużo szarej strefy. Wreszcie, zaufaj swojemu przeczuciu, jeśli boisz się tego zrobić, to prawdopodobnie jest „duże”.
Refaktoryzacja z definicji nie daje żadnej widocznej funkcjonalności, niczego, co można pokazać klientowi, żadnych rezultatów. W najlepszym przypadku mogą one przynieść niewielką poprawę szybkości i wykorzystania pamięci, ale nie jest to główny cel. Można powiedzieć, że głównym celem jest kod, z którego jesteś zadowolony. Ale ponieważ zmieniasz kod w taki sposób, że ma to daleko idące konsekwencje w całym kodzie, jest szansa, że rozpęta się piekło i pojawią się problemy. Stąd oczywiście bierze się lęk, o którym wspomnieliśmy. Czy kiedykolwiek wprowadziłeś kogoś nowego do swojej bazy kodu i po tym, jak zapytał o fragment osobliwie zorganizowanego kodu, odpowiedziałeś czymś w stylu:
Taaaaaaaaaaaaaaaaaa ta wersja kodu miała wtedy sens, ale specyfikacje się zmieniły i teraz jest zbyt drogi aby go naprawić?
Może nawet spojrzałeś na nich bardzo poważnie i kazałeś im zostawić to w spokoju i nie dotykać.
Pytanie: „Dlaczego mielibyśmy to robić?” jest naturalny i może być tak samo ważny jak proces refaktoryzacji, ponieważ dość często trzeba przekonać inne osoby, aby móc poświęcić swój kosztowny czas na refaktoryzację. Zastanówmy się więc nad przypadkami, w których chciałbyś to zrobić i korzyściami, jakie można osiągnąć:
Ulepszenia w wydajności
Jesteś zadowolony z obecnej organizacji kodu od punktu konserwacji, ale nadal powoduje to problemy z wydajnością. Optymalizacja aktualnej konfiguracji jest po prostu zbyt trudna, a zmiany byłyby bardzo kruche.
Jest tylko jedna rzecz do zrobienia, a mianowicie jej obszerne profilowanie. Przeprowadź testy porównawcze i oszacuj, ile zyskasz, a następnie spróbuj oszacować, jak przełoży się to na konkretne zyski. Czasami możesz nawet zdać sobie sprawę, że proponowana refaktoryzacja kodu nie jest tego warta. Innym razem będziesz mieć zimne twarde dane na poparcie swojej sprawy.
Ulepszenia architektoniczne
Może architektura jest w porządku, ale nieco przestarzała, a może jest tak zła, że kulisz się za każdym razem, gdy dotykasz tej części bazy kodu. Działa dobrze i szybko, ale dodanie nowych funkcji jest uciążliwe. W tym bólu leży biznesowa wartość refaktoryzacji. „Ból” oznacza również, że proces refaktoryzacji potrwa dłużej, aby dodać nowe funkcje, może znacznie dłużej.
I można odnieść korzyść. Oszacuj koszty/korzyści dla kilku przykładowych funkcji z lub bez proponowanej dużej refaktoryzacji. Wyjaśnij, że podobne różnice będą dotyczyć większości nadchodzących funkcji dotyczących tej części systemu teraz i na zawsze w przyszłości, gdy system jest rozwijany. Twoje szacunki mogą być błędne, ponieważ często są one opracowywane w przypadku tworzenia oprogramowania, ale ich wskaźniki prawdopodobnie będą się sprawdzać.
Aktualizuję
Czasami kod jest początkowo dobrze napisany. Jesteś z tego bardzo zadowolony. Jest szybki, wydajny pamięciowo, łatwy w utrzymaniu i dobrze dostosowany do specyfikacji. Początkowo. Ale wtedy zmieniają się specyfikacje, zmieniają się cele biznesowe lub dowiadujesz się czegoś nowego o swoich użytkownikach końcowych, co unieważnia Twoje początkowe założenia. Kod nadal działa dobrze i nadal jesteś z niego zadowolony, ale coś jest po prostu niewygodne, gdy patrzysz na to w kontekście produktu końcowego. Rzeczy są umieszczone w nieco niewłaściwym podsystemie lub właściwości znajdują się w niewłaściwej klasie, a może niektóre nazwy nie mają już sensu. Pełnią teraz rolę, która w biznesie jest nazywana zupełnie inaczej. Jednak nadal bardzo trudno jest uzasadnić jakąkolwiek refaktoryzację Railsów na dużą skalę, ponieważ praca ta będzie na dużą skalę z każdym z innych przykładów, ale korzyści są znacznie mniej namacalne. Kiedy się nad tym zastanowić, utrzymanie go wcale nie jest takie trudne. Musisz tylko pamiętać, że niektóre rzeczy są w rzeczywistości czymś innym. Musisz tylko pamiętać, że A faktycznie oznacza B, a własność Y na A faktycznie odnosi się do C.
I na tym polega prawdziwa korzyść. W dziedzinie neuropsychologii istnieje wiele eksperymentów sugerujących, że nasza pamięć krótkotrwała lub robocza jest w stanie pomieścić zaledwie 7 +/- 2 elementów, jednym z nich jest eksperyment Sternberga. Kiedy studiujemy dany przedmiot, zaczynamy od podstawowych elementów i początkowo, gdy myślimy o pojęciach wyższego poziomu, musimy pomyśleć o ich definicjach. Rozważmy na przykład prosty termin „solone hasło SHA256”. Początkowo musimy przechowywać w naszej pamięci roboczej definicje „solonych” i „SHA256”, a może nawet definicję „funkcji mieszającej”. Ale kiedy w pełni zrozumiemy ten termin, zajmuje tylko jedno miejsce w pamięci, ponieważ rozumiemy go intuicyjnie. Jest to jeden z powodów, dla których musimy w pełni zrozumieć koncepcje niższego poziomu, aby móc wnioskować o tych z wyższego poziomu. To samo dotyczy terminów i definicji specyficznych dla naszego projektu. Ale jeśli musimy pamiętać tłumaczenie do prawdziwego znaczenia za każdym razem, gdy omawiamy nasz kod, to tłumaczenie zajmuje kolejny z tych cennych miejsc w pamięci roboczej. Wytwarza obciążenie poznawcze i utrudnia rozumowanie za pomocą logiki w naszym kodzie. Z kolei, jeśli trudniej to uzasadnić, oznacza to, że istnieje większa szansa, że przeoczymy ważny punkt i wprowadzimy błąd.
I nie zapominajmy o bardziej oczywistych skutkach ubocznych. Istnieje duża szansa na zamieszanie podczas omawiania zmian z naszym klientem lub kimkolwiek, kto zna tylko prawidłowe warunki biznesowe. Nowe osoby dołączające do zespołu muszą zapoznać się zarówno z terminologią biznesową, jak i jej odpowiednikami w kodzie.
Myślę, że te powody są bardzo przekonujące i uzasadniają koszt refaktoryzacji w wielu przypadkach. Mimo to bądź ostrożny, może być wiele skrajnych przypadków, w których będziesz musiał użyć swojej najlepszej oceny, aby określić, kiedy i jak dokonać refaktoryzacji.
Ostatecznie refaktoryzacja na dużą skalę jest dobra z tych samych powodów, dla których wielu z nas lubi rozpoczynać nowy projekt. Patrzysz na ten pusty plik źródłowy i nowy wspaniały świat zaczyna wirować w twoim umyśle. Tym razem zrobisz to dobrze, kod będzie elegancki, będzie zarówno pięknie rozplanowany, jak i szybki, solidny i łatwo rozszerzalny, a co najważniejsze, praca z nim będzie przyjemnością każdego dnia. Refaktoryzacja na małą i dużą skalę pozwala odzyskać to uczucie, tchnąć nowe życie w starą bazę kodu i spłacić dług techniczny.
Na koniec najlepiej jest, jeśli refaktoryzacja jest napędzana planami, aby ułatwić wdrożenie pewnej nowej funkcji. W takim przypadku refaktoryzacja będzie bardziej skoncentrowana, a wiele czasu spędzonego na refaktoryzacji zostanie natychmiast odzyskane dzięki szybszej implementacji samej funkcji.
Przygotowanie
Upewnij się, że pokrycie testowe jest bardzo dobre we wszystkich obszarach bazy kodu, których możesz dotknąć. Jeśli zauważysz pewne części, które nie są dobrze pokryte, najpierw poświęć trochę czasu na zwiększenie zasięgu testu. Jeśli w ogóle nie masz testów, powinieneś najpierw poświęcić czas na ich tworzenie. Jeśli nie możesz stworzyć odpowiedniego zestawu testów, skoncentruj się na testach akceptacyjnych i napisz tyle, ile możesz, i upewnij się, że piszesz testy jednostkowe podczas refaktoryzacji. Teoretycznie możesz przeprowadzić refaktoryzację kodu bez dobrego pokrycia testami, ale będzie to wymagało od Ciebie wielu ręcznych testów i robienia tego często. Potrwa to znacznie dłużej i będzie bardziej podatne na błędy. Ostatecznie, jeśli pokrycie twojego testu nie jest wystarczająco dobre, koszt przeprowadzenia refaktoryzacji Railsów na dużą skalę może być tak wysoki, że powinieneś, niestety, rozważyć nie robienie tego w ogóle. Moim zdaniem jest to zaleta testów automatycznych, która nie jest wystarczająco często podkreślana. Zautomatyzowane testy pozwalają na częstą i co ważniejsze refaktoryzację, aby być odważniejszym.
Po upewnieniu się, że pokrycie testami jest dobre, nadszedł czas, aby rozpocząć mapowanie zmian. Na początku nie powinieneś zajmować się kodowaniem. Musisz z grubsza zmapować wszystkie zaangażowane zmiany i prześledzić wszystkie konsekwencje w bazie kodu, a także załadować wiedzę na ten temat do swojego umysłu. Twoim celem jest dokładne zrozumienie, dlaczego coś zmieniasz i jaką rolę odgrywa w kodzie. Jeśli natkniesz się na to, zmieniając rzeczy tylko dlatego, że wyglądają, jakby wymagały zmiany lub dlatego, że coś się zepsuło, a to wydaje się to naprawić, prawdopodobnie skończysz w martwym zaułku. Wydaje się, że nowy kod działa, ale niepoprawnie, a teraz nawet nie pamiętasz wszystkich wprowadzonych zmian. W tym momencie może być konieczne porzucenie pracy, którą wykonałeś przy refaktoryzacji kodu na dużą skalę i zasadniczo zmarnowałeś swój czas. Dlatego nie spiesz się i zapoznaj się z kodem, aby zrozumieć konsekwencje każdej zmiany, którą zamierzasz wprowadzić. W końcu to sowicie się opłaci.
Będziesz potrzebować pomocy w procesie refaktoryzacji. Może wolisz coś innego, ale ja lubię zwykły kawałek papieru i długopis. Zaczynam od napisania początkowej zmiany, którą chcę wprowadzić w lewym górnym rogu papieru. Następnie zaczynam szukać wszystkich miejsc dotkniętych zmianą i zapisuję je pod początkową zmianą. Tutaj ważne jest, aby kierować się własnym osądem. Ostatecznie notatki i diagramy na papierze są dostępne dla Ciebie, więc wybierz styl, który najlepiej pasuje do Twojej pamięci. Piszę krótkie fragmenty kodu ze znakami punktorów pod nimi i dużą ilością strzałek prowadzących do innych tego typu notatek, wskazujących rzeczy, które od niego zależą, bezpośrednio (pełna strzałka) lub pośrednio (strzałki przerywane). Dodaję również adnotacje do strzałek za pomocą skróconych znaków jako przypomnienie jakiejś konkretnej rzeczy, którą zauważyłem w bazie kodu. Pamiętaj, że będziesz wracać do tych notatek tylko w ciągu najbliższych kilku dni, podczas gdy będziesz wprowadzać zaplanowane w nich zmiany, i możesz używać bardzo krótkich i tajemniczych przypomnień, aby zajmowały mniej miejsca i były łatwiejsze do rozmieszczenia na papierze . Kilka razy sprzątałem swoje biurko miesiące po refaktoryzacji Railsów i znalazłem jeden z tych dokumentów. To był kompletny bełkot, absolutnie nie miałem pojęcia, co oznacza coś na tej kartce, z wyjątkiem tego, że mógł to napisać ktoś, kto oszalał. Ale wiem, że ta kartka była niezbędna, kiedy pracowałem nad tym problemem. Nie myśl też, że musisz zapisywać każdą zmianę. Możesz je grupować i śledzić szczegóły w inny sposób. Na przykład w swoim głównym artykule możesz zauważyć, że musisz „zmienić nazwy wszystkich wystąpień Ab na Cd”, a następnie możesz śledzić szczegóły na kilka różnych sposobów. Możesz zapisać je wszystkie na osobnej kartce papieru, możesz zaplanować ponowne globalne wyszukiwanie wszystkich wystąpień lub po prostu pozostawić wszystkie pliki źródłowe, w których zmiana ma zostać otwarta w wybranym edytorze i zanotuj sobie w pamięci, aby wrócić do nich, gdy skończysz mapowanie zmian.

Kiedy określisz konsekwencje swojej początkowej zmiany, ponieważ jest to duża skala, najprawdopodobniej zidentyfikujesz dodatkowe zmiany, które same mają dalsze konsekwencje. Powtórz analizę również dla nich, odnotowując wszystkie zależne zmiany. W zależności od wielkości zmian możesz je zapisać na tej samej kartce papieru lub wybrać nową pustą. Bardzo ważną rzeczą do zrobienia podczas mapowania zmian jest próba zidentyfikowania granic, w których można faktycznie zatrzymać zmiany rozgałęzień. Chcesz ograniczyć refaktoryzację do najmniejszego sensownego, zaokrąglonego zestawu zmian. Jeśli widzisz punkt, w którym możesz po prostu zatrzymać się i pozostawić resztę tak, jak jest, zrób to, nawet jeśli widzisz, że powinna zostać zrefaktorowana, nawet jeśli jest to związane z innymi zmianami. Zakończ tę rundę refaktoryzacji kodu, dokładnie przetestuj, wdróż i wróć po więcej. Powinieneś aktywnie szukać tych punktów, aby zachować kontrolę nad wielkością zmian. Oczywiście, jak zawsze, dokonaj osądu. Dość często dochodziłem do punktu, w którym mogłem odciąć proces refaktoryzacji, dodając kilka klas proxy, aby trochę przetłumaczyć interfejs. Zacząłem je nawet wdrażać, gdy zdałem sobie sprawę, że będą one tak samo pracochłonne, jak przesunięcie refaktoryzacji nieco dalej do punktu, w którym nastąpi „naturalny przystanek” (tj. prawie nie będzie potrzebny kod proxy). Następnie cofnąłem się, cofając moje ostatnie zmiany i refaktoryzowany. Jeśli to wszystko brzmi trochę jak mapowanie niezbadanych terytoriów, to dlatego, że tak mi się wydaje, z wyjątkiem tego, że mapy terytoriów są tylko dwuwymiarowe.
Wykonanie
Po zakończeniu przygotowań do refaktoryzacji nadszedł czas na wykonanie planu. Upewnij się, że Twoja koncentracja jest w górze i zapewnij sobie środowisko wolne od zakłóceń. Czasami posuwam się w tym momencie do całkowitego wyłączenia połączenia internetowego. Chodzi o to, że jeśli dobrze się przygotowałeś, miej przy sobie dobry zestaw notatek na papierze, a twoja koncentracja jest większa! W ten sposób często można bardzo szybko przejść przez zmiany. Teoretycznie większość pracy została wykonana wcześniej, podczas przygotowań.
Kiedy już dokonasz refaktoryzacji kodu, zwróć uwagę na dziwne fragmenty kodu, które robią coś bardzo konkretnego i mogą wydawać się złym kodem. Może są to zły kod, ale dość często mają do czynienia z dziwnym przypadkiem, który został odkryty podczas badania błędu w produkcji. Z biegiem czasu większość kodu Railsów rozwija się „włosy” lub „brodawki”, które obsługują dziwne błędy w narożnych przypadkach, na przykład dziwny kod odpowiedzi tutaj, który może być potrzebny dla IE6 lub warunków, które obsługują dziwny błąd synchronizacji. Nie są one ważne dla całościowego obrazu, ale nadal są istotnymi szczegółami. Najlepiej byłoby, gdyby były one wyraźnie objęte testami jednostkowymi, jeśli nie, spróbuj je najpierw objąć. Kiedyś miałem za zadanie przeportować średniej wielkości aplikację z Rails 2 do Rails 3. Dobrze znałem kod, ale był trochę nieuporządkowany i było wiele zmian, które musiałem wziąć pod uwagę, więc zdecydowałem się na reimplementację. Właściwie nie była to prawdziwa reimplementacja, ponieważ prawie nigdy nie jest to sprytne posunięcie, ale zacząłem od pustej aplikacji Rails 3 i przerobiłem pionowe wycinki starej aplikacji na nową, z grubsza używając opisanego procesu. Za każdym razem, gdy kończyłem pionowy kawałek, przechodziłem przez stary kod Railsów, patrząc na każdy wiersz i dwukrotnie sprawdzając, czy ma on swój odpowiednik w nowym kodzie. Zasadniczo wybierałem wszystkie stare „włosy” kodu i replikowałem je w nowej bazie kodu. Ostatecznie w nowej bazie kodu rozwiązano wszystkie narożne przypadki.
Upewnij się, że wykonujesz testy ręczne wystarczająco często. Zmusi Cię to zarówno do szukania naturalnych „przerw” w procesie refaktoryzacji, które pozwolą Ci przetestować część systemu, jak i dadzą Ci pewność, że nie złamałeś niczego, czego nie spodziewałeś się złamać w procesie .
Zawiń to
Po zakończeniu refaktoryzacji kodu Rails, upewnij się, że przeglądasz wszystkie zmiany po raz ostatni. Spójrz na całą różnicę i przejrzyj ją. Dość często zauważysz subtelne rzeczy, które przegapiłeś na początku refaktoryzacji, ponieważ nie miałeś wiedzy, którą masz teraz. Jest to miła zaleta refaktoryzacji na dużą skalę: otrzymujesz wyraźniejszy obraz organizacji kodu, zwłaszcza jeśli pierwotnie tego nie napisałeś.
Jeśli to w ogóle możliwe, poproś kolegę, aby to również przejrzał. Nie musi nawet być szczególnie zaznajomiony z tą dokładną częścią kodu, ale powinien mieć ogólną znajomość projektu i jego kodu. Posiadanie świeżego spojrzenia na zmiany może bardzo pomóc. Jeśli absolutnie nie możesz nakłonić innego programisty do obejrzenia ich, musisz sam udawać, że jesteś jednym z nich. Wyśpij się w nocy i przejrzyj to ze świeżym umysłem.
Jeśli nie masz kontroli jakości, będziesz musiał również nosić ten kapelusz. Ponownie zrób sobie przerwę i zdystansuj się od kodu, a następnie wróć do ręcznego testowania. Właśnie przeszedłeś ekwiwalent wejścia do zagraconej szafki z okablowaniem elektrycznym z kilkoma narzędziami i uporządkowałeś wszystko, prawdopodobnie przecinając i zmieniając okablowanie, więc należy zachować nieco większą ostrożność niż zwykle.
Wreszcie ciesz się owocami swojej pracy, biorąc pod uwagę wszystkie planowane zmiany, które teraz będą znacznie czystsze i łatwiejsze do wdrożenia.
Kiedy byś tego nie zrobił?
Chociaż regularne wykonywanie refaktoryzacji na dużą skalę w celu utrzymania aktualności i wysokiej jakości kodu projektu niesie ze sobą wiele korzyści, nadal jest to bardzo kosztowna operacja. Zdarzają się również przypadki, w których nie byłoby to wskazane:
Twój zasięg testowy jest słaby
Jak już wspomniano: bardzo słabe pokrycie testami może być dużym problemem. Kieruj się własnym osądem, ale na krótką metę lepiej skupić się na zwiększeniu zasięgu podczas pracy nad nowymi funkcjami i wykonywania jak największej liczby lokalnych refaktoryzacji na małą skalę. Pomoże ci to bardzo, gdy zdecydujesz się pogrążyć i posortować większe części bazy kodu.
Refaktoryzacja nie jest napędzana nową funkcją, a baza kodu nie zmieniła się od dłuższego czasu
Użyłem czasu przeszłego, zamiast celowo powiedzieć „baza kodu się nie zmieni”. Sądząc z doświadczenia (przez doświadczenie mam na myśli to, że wielokrotnie się myliłem), prawie nigdy nie możesz polegać na swoich przewidywaniach, kiedy jakaś część kodu będzie musiała zostać zmieniona. Więc zrób następną najlepszą rzecz: spójrz w przeszłość i załóż, że przeszłość się powtórzy. Jeśli coś nie było zmieniane przez długi czas, prawdopodobnie nie musisz tego teraz zmieniać. Poczekaj, aż ta zmiana nadejdzie i popracuj nad czymś innym.
Jesteś pod presją czasu
Konserwacja jest najdroższą częścią cyklu życia projektu, a refaktoryzacja sprawia, że jest tańsza. Refaktoryzacja jest absolutnie niezbędna dla każdej firmy, aby zmniejszyć zadłużenie techniczne, aby w przyszłości konserwacja była tańsza. W przeciwnym razie grozi mu wejście w błędne koło, w którym dodawanie nowych funkcji staje się coraz droższe. Mam nadzieję, że to oczywiste, dlaczego tak jest źle.
To powiedziawszy, refaktoryzacja na dużą skalę jest bardzo, bardzo nieprzewidywalna, jeśli chodzi o to, jak długo zajmie, i nie powinieneś robić tego w połowie drogi. Jeśli z jakichkolwiek wewnętrznych lub zewnętrznych powodów jesteś pod presją czasu i nie jesteś pewien, czy będziesz w stanie zakończyć w tym czasie, być może będziesz musiał zrezygnować z refaktoryzacji. Presja i stres, zwłaszcza wywołany czasem, prowadzą do niższego poziomu koncentracji, co jest absolutnie konieczne w przypadku refaktoryzacji na dużą skalę. Pracuj nad uzyskaniem większego „wkupu” od swojego zespołu, aby zarezerwować na to czas i zajrzeć do swojego kalendarza na okres, w którym będziesz miał czas. Nie jest konieczne, aby był to ciągły ciąg czasu. Oczywiście będziesz miał inne problemy do rozwiązania, ale te przerwy nie powinny być dłuższe niż dzień lub dwa. Jeśli tak, będziesz musiał przypomnieć sobie swój własny plan, ponieważ zaczniesz zapominać, czego nauczyłeś się o bazie kodu i gdzie dokładnie się zatrzymałeś.
Wniosek
Mam nadzieję, że udzieliłem Ci kilku przydatnych wskazówek i przekonałem Cię o korzyściach, a śmiem twierdzić, że konieczne jest przeprowadzanie refaktoryzacji na dużą skalę w określonych sytuacjach. Temat jest bardzo niejasny i oczywiście nic, co zostało tutaj powiedziane, nie jest definitywną prawdą, a szczegóły będą się różnić w zależności od projektu. Starałem się udzielić rad, które moim zdaniem są powszechnie obowiązujące, ale jak zwykle rozważ swój konkretny przypadek i wykorzystaj własne doświadczenie, aby dostosować się do jego konkretnych wyzwań. Powodzenia w refaktoryzacji!