Ogólne zasady, wzorce – z jednej strony pozwalają uporządkować wiedzę, stosować wspólne podejście przy rozwiązywaniu pewnych problemów. Z drugiej strony mogą znacząco utrudnić naszą kreatywność i ograniczyć inspiracje. Ale nawet wtedy mamy coś co możemy sprawdzić i być może to odrzucić aby wymyślić coś lepszego.

W przypadku refaktoryzacji, aby móc ją skutecznie wykonać, zauważyłem taką regułę i nadałem jej nazwę „Piramida Refaktoryzacji”. Zasada ta pozwala podejść do refaktoryzacji od najmniejszych możliwych przekształceń do coraz bardziej złożonych.

Koncepcja ta opiera się na założeniu, że nie powinniśmy (chociaż czasem możemy) przechodzić do większych refaktoryzacji, takich jak wyodrębnienie nowej klasy, nowej metody, zanim zakończymy proces upraszczania logiki algorytmu (tj. przepływu działania). Przejrzysty kod można łatwo i szybko czytać i zrozumieć. Oznacza to, że prawdopodobnie nie powinien on zawierać takich rzeczy jak tajemnicze nazwy pól i zmiennych, wielokrotnie zagnieżdżone warunki lub zagnieżdżone pętle. Brak czytelności z powodu nadmiaru zmiennych lokalnych także może zostać znacząco ograniczony np. poprzez pozbycie się reguły pojedynczego wyjścia z metody i umieszczenie punktów wyjścia w kilku miejscach. Podejście to umożliwi następnie ekstrakcję metod zawierających kod o niższym poziomie abstrakcji.

W jaki sposób zauważyłem tą prawidłowość? W ciągu ostatnich 7-8 lat przeprowadziłem ponad 100 warsztatów na temat refaktoryzacji. Zawsze korzystałem z koncepcji przedstawionych w dwóch podstawowych książkach na temat refaktoryzacji. Pierwsza to książka Martina Fowlera “Refaktoryzacja” którą zawsze postrzegałem jako katalog. Druga „Refaktoryzacja do wzorców” Joshua Kerievsky’ego była zawsze rodzajem „wytycznych kroków” do naśladowania podczas przechodzenia od zastanego kodu do implementacji danego wzorca. Koncepcja piramidy refaktoryzacji znajduje się pomiędzy jak i w każdej z tych książek, chociaż taka nazwa nie występuje w żadnej z nich.

W przypadku książki „Refaktoryzacja” Martina Fowlera – każda transformacja może być umieszczona gdzieś wyżej lub niżej na piramidzie refaktoryzacji. Na przykład “ekstrakcja parametru” to na “poziom metod”, wyłonienie klasy bazowej rozpoczyna “poziom klas”. Jednak wchłonięcie zmiennej lokalnej lub jej ekstrakcja z pewnością ma swoje miejsce w najniższej (lub raczej podstawowej!) warstwie piramidy. Ekstrakcja klasy bazowej aby przenieść to niej metodę szablonu (template method) to z pewnością poziom abstrakcji i wzorców. Podobnie będzie z “ukryciem” klasy za interfejsem command czy factory.

Druga książka Joshua Kerievsky’ego („Refactoring to Patterns”) zachęca nas z tematem refaktoryzacji dużo dalej – robiąc to na podstawie przypadków użycia. Jest to kontynuacja powyższej książki Martina Fowlera. Zawiera wiele refaktoryzacji kodu zastanego do wybranych wzorców projektowych. Każdy z tych przykładów może zostać podzielony na zestaw mniejszych przekształceń, które przechodzą od dołu piramidy w kierunku jej wierzchołka.

Na przykład, aby wyodrębnić wzorzec projektowania poleceń (command), zaczynamy od wyodrębniania części instrukcji switch / if-else do mniejszych metod (metod o niższym poziomie abstrakcji). Następnie umieszczamy każdą z tych metod w nowej klasie, a potem wyodrębniamy interfejs implementowany przez każdą z tych wyodrębnionych klas. Ostatecznie główna klasa deleguje wykonanie logiki to poszczególnych klas który zostały ukryte za abstrakcją interfejsu komendy (command).

W następnym artykule opiszę jak piramida refaktoryzacji staje się widoczna i jak została użyta. Zrobię to na podstawie refaktoryzacji do wzorca interpreter która jest opisana (bez użycia koncepcji piramidy refaktoryzacji) w książce “Refaktoryzacja do Wzorców” Joshua Kerievskiego.

Spread the word. Share this post!