Niewidoczne zmiany na lepsze – refactoring

Podczas jednego z kursów online, który miałem przyjemność niedawno zorganizować, pojawiło się pytanie czym dokładnie jest refactoring. Nie przepadam za polskim tłumaczeniem tego terminu, ponieważ Refaktoryzacja nie brzmi dla mnie wcale lepiej i zgaduję, że koniec końców, jest to i tak zapożyczenie z angielskiego.

Zmieniać, aby nie zmieniać.

W gruncie rzeczy chodzi właśnie o to. W takiej formie brzmi to rzeczywiście idiotycznie, więc należy się tu szybkie sprostowanie. W kontekście programowania chodzi o zmienianie kodu programu, bez zmiany rezultatu jego działania. Po co? Niestety to pytanie zadaje sobie wiele zespołów programistycznych, kompletnie nie dopuszczając tej idei do swojego rozumowania.
Ja sam z tym procesem spotkałem się dopiero w mojej bodajże… czwartej pracy w zawodzie.

Doświadczenie daje perspektywę

Jeżeli dopiero zaczynasz swoją przygodę z programowaniem, z pewnością zadajesz sobie pytanie: po co zmieniać coś co już działa? Przecież tyle wysiłku zostało włożone w to, by ten kod poskładać razem, uruchomić, zademonstrować. Teraz można już tylko zepsuć, prawda?

Z perspektywy czasu widać jednak, że kod, który działa dzisiaj może nie działać jutro, lub sprawić problemy przy kolejnych jego modyfikacjach. Jeżeli kod jest jak trawnik, który wiecznie rośnie – nierówno posiany będzie też nierówno rósł. Ta ogrodnicza metafora mana celu pokazanie, że zrobienie czegoś dobrze na początku zawsze zaowocuje w przyszłości.

Co zmieniać, jak zmieniać?

Refactoring może się przejawiać w kilku formach czy stopniach zaawansowania. Można między innymi zaobserwować:

  • Proste zmiany lub ujednolicenie nazw zmiennych/funkcji w celu poprawy czytelności
  • Grupowanie funkcjonalności w klasy lub oddzielne pliki
  • Uproszczenie zależności pomiędzy modułami w celu usprawnienia architektury systemu
  • Często w ogóle sprawienie, by kod stał się „testowalny” (dość ogólnie)
  • Poprawa wydajności kodu poprzez usprawnienie algorytmów lub podmianę biblioteki
  • Przygotowanie kodu pod użycie nowych funkcjonalności danego języka (np. php 5.6 do php 7)

Takich przykładów idzie znaleźć jeszcze kilka, ale jak widać żaden z nich w teorii nie powinien zmienić sposobu działania programu. Jeżeli pojawiają się widoczne zmiany, oznacza to, że coś w naszym procesie poszło nie tak i należy się temu przyjrzeć.

Generalnie zmieniamy na lepsze. Staramy się myśleć o przyszłości, żeby również kiedyś rozwój tego samego kawałka kodu był przyjemnością, a nie koszmarem. Często refactoring jest naturalną fazą po dokonaniu tzw. „proof of concept”, czyli zazwyczaj posklejanego na szybko kodu w celu udowodnienia lub zaprezentowania jakiegoś pomysłu. Jeżeli pomysł ma być rozwijany dalej, wypadałoby go przejrzeć i odświeżyć, zrobić „na porządnie”.

Niestety w praktyce mało kto wierzy w sens tej idei i potem wielu z nas musi pracować nad kodem, który od zawsze był tym wspominanym posklejanym kawałkiem kodów, który wiecznie stwarza problemy, powoduje i każda kolejna modyfikacja przyprawia o co najmniej ból głowy.

Kod przetestowany łatwiej jest zmieniać

Na koniec chciałbym jeszcze podrzucić pro-tip, czyli wspomnieć o tym jak testy jednostkowe nadają procesowi refactoringu pewnej głębii. Otóż jeżeli celem tego procesu są zmiany kodu, bez zmiany sposobu działania, to która lampka powinna zapalić się w głowach? Ano właśnie testy jednostkowe. Kod programu solidnie obłożony testami jest dużo wygodniejszy do przerabiania, ponieważ jeżeli coś zepsujemy to testy nam to bardzo chętnie wypomną i cały proces staje się jaśniejszy i bezpieczniejszy.

Mam cichą nadzieję, że udało mi się chociaż trochę przekonać Cię do rozważenia tej techniki w swojej codziennej pracy programisty. 🙂