IT eSky.pl

RSS

Przepis na udany refaktoring

Inspiracją do napisania tego artykułu był remont, który miałam wątpliwą przyjemność przeprowadzić w poprzednim miesiącu. Oczywiście nie sama, tylko z mężem. I gromadką dzieci, które skutecznie utrudniały podjęcie efektywnych działań. Był też deadline oraz cała masa nieprzewidzianych okoliczności. Przypomina Wam to coś?

Walcząc z kuchnią potrzebowałam zagadnienia, którym mogłabym zająć umysł, co pozwoliłoby mi się odciąć od żmudnych czynności. Pomiędzy jednym a drugim bezmyślnym maźnięciem pędzla naszła mnie refleksja nad podobieństwem między refaktoryzacją, zwłaszcza kodu, który jest legacy, a remontem mieszkania. I nad nieuchronnością niemiłych niespodzianek, które w obu przypadkach są, moim skromnym zdaniem, nieuniknione.

Choć z biegiem czasu nabieramy doświadczenia, wciąż może się zdarzyć, że seria zaskakujących wypadków i krnąbrność materii, z którą się ścieramy, mocno utrudni oraz spowolni naszą pracę. Już wcześniej koledzy z zespołu podpuszczali mnie, bym opisała swoje przemyślenia się na ten temat, przed czym dzielnie się broniłam. Jednak starcie z  remontem zmobilizowało mnie, bym podjęła to wyzwanie.

A zatem…

Zacznijmy od podstaw – czym jest refaktoring

Refaktoring to zmiany w aplikacji, które mają na celu osiągnięcie lub utrzymanie wysokiej jakości kodu. Zazwyczaj wynikają, a przynajmniej powinny wynikać z potrzeb biznesowych. I choć zwykle refaktoryzacja nie wiąże się ze zmianą czy poszerzeniem danej funkcjonalności, w przypadku legacy code jest to zazwyczaj konieczność.

Wobec tego co możemy zrobić, by zminimalizować ryzyko opóźnień i zagwarantować pozytywne zakończenie podjętego refaktoringu?

1. Obtestujmy istniejącą funkcjonalność

Jeśli kod nie posiada testów do refaktoryzowanej funkcjonalności, koniecznie rozpocznijmy od ich stworzenia. Niezbędne będą testy charakteryzacyjne, którymi obejmiemy możliwie jak najdokładniej zmienianą funkcjonalność, co pozwoli nam się ustrzec przed błędami wynikającymi z niechcianych zmian w działaniu aplikacji.

  • Osobiście uważam, że o ile samo pisanie takich testów może być uciążliwe, to już korzystanie z nich jest frajdą. Zamiast ręcznie testować zmiany, wystarczyć tylko po każdej poprawce puścić wcześniej przygotowane testy.
  • Dużym plusem jest także to, że często przygotowane testy, po zrefaktoryzowaniu, możemy wykorzystać jako testy jednostkowe do poprawionej funkcjonalności.

2. Wydzielajmy małe partie kodu

Kroki refaktoringu powinny być jak najmniejsze. Łatwiej wówczas skończyć daną partię kodu, dzięki czemu w sytuacjach losowych możliwe jest oddanie lub przekazanie innemu członkowi zespołu skończonej części zadania.

  • Jak to zrobić? Np z dużej metody wydzielając jedną operację i przenosząc ją drobnymi krokami do osobnej metody i klasy.

3. Odpalajmy testy po każdej iteracji (po każdym małym kroku)

Zmniejsza to ryzyko błędów oraz chroni przed skomplikowanym debugowaniem, gdy po większych zmianach kod przestanie działać.

4. Wybierajmy proste rozwiązania

Projektujmy bazując na tym, co traktowane jest jako pewnik. Nie rozbudowujmy nadmiernie aplikacji pod kątem przyszłych rozwiązań, jeśli nie wiemy, czy będą wymagane. Jednak gdy ewidentnie wiadomo, w którym kierunku rozwijać się będzie aplikacja, przygotujmy rozwiązanie, które umożliwi rozszerzenie funkcjonalności w prosty sposób.

5. Wystawmy kod jak najszybciej

Staramy się jak najszybciej wystawić zrefaktoryzowany kod na produkcję – im dłużej znajduje się on na osobnej gałęzi, tym trudniej go utrzymać.

  • Po za tym testowanie na środowisku, dla którego na bieżąco uruchamiane są testy regresyjne, pozwoli szybciej i z większą skutecznością wykryć ewentualne błędy w działaniu aplikacji.

6. Pamiętajmy o odpoczynku

Skupiając się na problemie często zapominamy o robieniu sobie przerw. A wbrew pozorom są one niezbędne, by nasza praca przebiegała efektywnie.

  • Świetnie sprawdzają się w tym przypadku techniki typu pomodoro, które pozwalają dłużej utrzymać koncentrację.
  • Ciekawym rozwiązaniem są power naps, które pozwalają odzyskać siły po intensywnie spędzonej części dnia.
  • Gdy żadna z powyższych opcji nie jest możliwa, lub nie przypadła nam do gustu, dobrze jest po prostu zrobić sobie przerwę, gdy czujemy, że tracimy motywację. To normalne. Przewietrzenie się czy przerwa na kawę też pozwolą podładować baterię.
  • Dbajmy również o wyspanie się – nieprzespane nocki czy praca po 12h wcale nie przyspieszy pracy. Nie nadgonimy w ten sposób roboty, wręcz przeciwnie, zmarnujemy siły i będziemy mniej wydajni!

7. Nie obawiajmy się prosić o pomoc

Czasem zdarza nam się zaciąć na jakimś problemie. Może to być błąd, wybór właściwego rozwiązania technologicznego, nierzadko nazwa metody. Jeśli zauważyliśmy, że przestój się przedłuża, np. o więcej niż godzinę – zdecydowanie jest to moment, by poprosić o radę kolegę z zespołu, czy choćby poprogramować z misiem ;)

  • Niejednokrotnie zwykłe „wygadanie się” wystarczy, by nasunęło nam się właściwe rozwiązanie.
  • Korzystanie z pomocy innych często bardzo przyspiesza pracę i odblokowuje.

8. Informujmy zespół o napotkanych problemach

Jednym jest zwrócenie się do konkretnej osoby z prośbą o radę, czym innym poinformowanie całego zespołu o potencjalnych opóźnieniach – wówczas to cały zespół powinien zadecydować, co dalej z tym fantem zrobić.

  • W większej grupie czasem łatwiej znaleźć właściwe rozwiązanie, lepsza jest też propagacja wiedzy. Może ktoś już borykał się z danym problemem, a może zna biznesowe wytyczne, o których powinniśmy wiedzieć, a nie zostały zawarte w zadaniu.

9. Poskrommy wewnętrznego perfekcjonistę

  • Każdy refaktoring można by prowadzić bez końca. Nigdy kod nie będzie dość idealny, by nie można było napisać go lepiej. Narzućmy sobie ramy czasowe, by refaktoryzacja nie trwała w nieskończoność.
  • Odrobina zdecydowania też może być pomocna. Nie traćmy czasu na niekończące się dywagacje z samym sobą – dotyczące nazw, struktury itp. Nie znaczy to, że mamy podejmować decyzje pochopnie. Ale nie rozmyślajmy bez końca – wypróbujmy rozwiązanie, zamiast je bezustannie rozważać – zawsze możemy zmienić decyzję.

10. Nie pozwólmy wyrwać się z rytmu

Nasze własne przerwy na naładowanie baterii są niezwykle ważne. Podobnie jak pomoc koledze, który głowi się nad wyjątkowo istotną kwestią. Ale sprawia to jednak, że musimy zgadzać się na każdą wymuszaną przez innych przerwę. Trudno wrócić do własnego rytmu, gdy ktoś nagle zajął nam umysł innym problemem. Ćwiczmy asertywność – często osoba zgłaszająca problem wcale nie potrzebuje naszej pomocy lub może na nią chwilę poczekać.

11. Oddzielmy aktualizację formatowania od zmiany funkcjonalności

Większa aktualizacja formatowania kodu zaciemni obraz zmian funkcjonalności. Dlatego najlepiej taką modyfikację zawrzeć w osobnym commicie.

12. Dobrze opiszmy temat „przekazywany dalej”

Obojętne, czy przekazujemy zadanie koledze, do dalszej realizacji, czy odkładamy je do wykonania w innym terminie

  • Wskażmy miejsca, które wymagają dokończenia oraz jasno określmy, jakie są co do nich wytyczne.
  • Jeśli zostały uzgodnione z właścicielem zadania jakieś zmiany, które nie zostały nigdzie zapisane – konieczne dopiszmy je do treści zadania.

13. Właściwe narzędzia

Tak jak podczas remontu długość włosia na wałku trzeba dobrać do faktury ściany, tak podczas refaktoringu warto zadbać o środowisko, na którym pracujemy. Uruchomienie poleceń phinga, puszczenie testów jednostkowych / integracyjnych przy pomocy IDE, czy podpięty pod to samo IDE debugger, to nie tylko fajne gadżety, ale przede wszystkim niewiarygodne usprawnienie naszej pracy.

Nie wierzę w  pechową trzynastkę i na niej kończę swoją listę. Jestem jednak otwarta na dobre rady, może przychodzi Wam do głowy coś, co można tu dodać? Zapraszam do dyskusji :)


Zobacz również