Software Craftsmanship: Wzorce projektowe. Hot or not?

Krzysztof Kempiński
kkempin’s dev blog
7 min readMay 13, 2024

W ramach podcastu “Porozmawiajmy o IT” miałem okazję porozmawiać z Łukaszem Drynkowskim z SOLID.Jobs o wzorcach projektowych w programowaniu

Posłuchaj naszej rozmowy w wersji audio 🎧 https://porozmawiajmyoit.pl/poit-245-software-craftsmanship-wzorce-projektowe-hot-or-not/

Nasze kolejne spotkanie w ramach cyklu podcastu o software craftsmanship. Spotykamy się, żeby rozmawiać o rzemiośle, żeby poruszyć tematy, z którymi my jako programiści na co dzień mamy do czynienia. Nasza wcześniejsza seria podcastów, do której oczywiście też odsyłamy, dotyczyła narzędzi. Tutaj poruszamy takie tematy jak programowanie obiektowe, funkcyjne, clean code, to, kim jest inżynier rozwiązań, czy też podejście Secure by Design, więc osoby zaciekawione jak najbardziej odsyłamy do tych wcześniejszych odcinków. A dzisiaj będziemy mówić o też istotnym, jakby nie było temacie, jakim są wzorce projektowe.

Nie będziemy chcieli jednak tutaj teoretyzować i omawiać poszczególnych wzorców, nie o to tutaj nam chodzi, jest mnóstwo materiałów w sieci, gdzie można sobie właśnie tę wiedzę odszukać, natomiast będziemy chcieli się podzielić naszymi spostrzeżeniami i doświadczeniami wynikającymi właśnie z używania wzorców projektowych.

Ja tak sobie myślę, że to jest tego typu narzędzie, którym wyrządzono tyle samo dobra co zła. Nie jest to narzędzie biało-czarne, do czego na pewno będziemy dzisiaj chcieli nawiązać. Po prostu jest to narzędzie. Jakby nie było, trzeba wykorzystywać je w odpowiedni sposób.

Myślę sobie, że tutaj nieco przewrotnie może rozpoczniemy to nasze dzisiejsze spotkanie i zamiast rozpocząć od mówienia o pozytywach, to spróbujemy rozpocząć od tego, jakie są niewłaściwe użycia albo nadużycia wzorców projektowych. Od czego myślisz, Łukasz, moglibyśmy w tym temacie zacząć?

Myślę, że pierwszym tutaj takim ryzykiem to jest ryzyko tzw. złotego młotka, czyli fiksujemy się na czymś, co poznaliśmy właśnie i próbujemy, widzimy wszędzie gwoździe, nawet jeśli dana rzecz gwoździem nie jest i po prostu próbujemy na siłę użyć danego wzorca, czyli się po prostu podekscytowaliśmy znajomością jakiegoś wzorca.

Mogę tutaj taką historię opowiedzieć: na studiach, pamiętam, robiliśmy z kolegą taki program typu peer-to-peer do przesyłania plików między dwoma komputerami. I pamiętam, że wzorzec command tam był. Wszędzie, gdzie się dało, to po prostu ten command, tak się tutaj na ten wzorzec command po prostu zafiksowaliśmy. Bardzo fajny wzorzec swoją drogą, ale jestem pewien, że na pewno nie zawsze, gdzie został użyty, miał sens.

I inny przykład: taki wzorzec template method. Też pamiętam właśnie, że jak go odkryłem, to o, jak fajnie można tutaj między te klasy różne zachowania wymusić, natomiast później dopiero przyszło takie otrzeźwienie, jakieś takie zrozumienie większe tematu. Też tutaj okazało się, że jednak template method używa dziedziczenia, które samo w sobie jakby nie jest antypaternem, ale nadużywanie dziedziczenia jak wiadomo już jest takim antypaternem i powoduje różnego typu problemy w trakcie programowania, w trakcie designu.

I np. taką alternatywą dla tego template method to, myślę, jest wzorzec strategii, który tutaj wtedy ma mniej tych wad. Oczywiście te użycia nie zawsze są takie same, nie zawsze można jedno zastąpić drugim, ale jak widać, są alternatywy. Nie zawsze też alternatywą musi być inny wzorzec projektowania. Czasami możemy użyć po prostu jakiegoś feature’a, który jest wbudowany w język programowania. Też te nowoczesne języki programowania, myślę, w tej chwili dużo tutaj tego, co dawały nam wzorce projektowe i tego, dlaczego te wzorce projektowe w ogóle powstały, to powstały, bo czegoś nie było w tych językach programowania, jakiejś możliwości. A już jesteśmy w 2024 roku i dużo tych wzorców projektowych jest gdzieś tam zaimplementowanych już w corze pewnych funkcji, pewnych bibliotek.

I np. taką alternatywą dla tego template method to, myślę, jest wzorzec strategii, który tutaj wtedy ma mniej tych wad. Oczywiście te użycia nie zawsze są takie same, nie zawsze można jedno zastąpić drugim, ale jak widać, są alternatywy. Nie zawsze też alternatywą musi być inny wzorzec projektowania. Czasami możemy użyć po prostu jakiegoś feature’a, który jest wbudowany w język programowania.

Właśnie, wiesz, niech pierwszy rzuci kamień ten, kto nie poznawszy jakiegoś wzorca projektowego, nie zaczął go używać wszędzie, bo wydawało się, że to jest tak idealne rozwiązanie, że sprawdzi się doskonale, tymczasem bardzo szybko prowadzi to do jakiegoś over engineeringu, później trudności ze zrozumieniem, co tak naprawdę artysta miał na myśli.

Tak, natomiast to nie jest tak, że wzorce projektowe są złe, tego też nie chcemy tutaj powiedzieć. Po prostu to jest narzędzie i musimy używać go z głową. Np. teraz, żeby dać taki kontrapunkt, uważam, że wzorce projektowe są świetnym narzędziem do tego, żeby się uczyć programować, żeby po prostu jak ktoś zaczyna swoją przygodę z kodem, to od razu jakieś takie dobre wzorce, gdzieś mu się tam te synapsy w mózgu połączą w odpowiedni sposób, na pewno więcej wśród wzorców projektowych jednak jest wzorców pozytywnych niż antywzorców.

Nawet jeśli któryś z tych tradycyjnych wzorców jest uznawany za antywzorzec, pewnie chłopiec do bicia Singleton, to jednak nie jest tak, że nie ma takiej sytuacji, gdzie ten Singleton by nie mógł być pozytywnie użyty, tak jak z Go2, niby złe, ale jednak ta jedna sytuacja na milion jest taka, że jednak ma to sens i o to właśnie chodzi, żebyśmy używali tego wszystkiego świadomie.

Dokładnie, powiedziałeś, że już na studiach byłeś zafascynowany przynajmniej niektórymi wzorcami projektowymi i myślę sobie, że właśnie ta prawda objawiona po części wynika z tego, że jakby wziąć dowolną listę sugerowanych książek w IT, to tam zawsze się znajdzie ta słynna pozycja od Gang of Four, Wzorce projektowe i właśnie chyba podchodzimy do tego w ten sposób, że to jest niejako księga objawiona, że tam jest prawda, w której powinniśmy pisać soft i w związku z tym to są jedyne słuszne rozwiązania.

Tymczasem, tak jak tutaj właśnie powiedziałeś, to jest jedynie pewne wprowadzenie rzeczy, które się gdzieś tam wcześniej sprawdziły, bo powiedzmy sobie szczerze, Gang of Four nie wymyślił tych wzorców projektowych, a przynajmniej nie wszystkie. To jest wynik lat doświadczeń programistów i zbierania różnych właśnie praktyk, które później można przekuć, tak jak w architekturze takiej tradycyjnej, w rozwiązania, które się zwyczajnie sprawdzają.

Tak, i też tutaj są różne rodzaje wzorców wzorce, które tu na poziomie, że tak powiem, takim operacyjnym używamy, ale są też wzorce takie architektoniczne, które są gdzieś tam level up, są wzorce, które mówią nam, jak np. moduły między sobą powinny się komunikować. Są też takie wzorce z kolei specyficzne dla języków programowania, np. JavaScript ma swoje wzorce, języki obiektowe mają swoje, też języki funkcyjne, to pewnie Ty więcej nam opowiesz, ale nie sądzę, żeby to były te same wzorce.

Z pewnością nie. Zanim do tego przejdziemy, bo to jest właśnie ciekawe, jak różne paradygmaty w ogóle podchodzą do wzorców projektowych, to jeszcze tutaj pozostając w tych nadużyciach wynikających ze złego, niepoprawnego albo nadmiernego używania wzorców projektowych, nie można nie wspomnieć o code review jako miejscu, jako takim obszarze, gdzie wzorce projektowe często potrafią rozpalić do czerwoności i potrafią wzbudzić świętą wojnę.

Bo właśnie tak jak powiedziałeś, ktoś zafascynowany jakimś wzorcem projektowym może próbować go na siłę forsować wszędzie, ponieważ wydaje się dla niego/dla niej, że to jest jedyne dobre rozwiązanie, a inna strona może albo po prostu uważać inaczej, albo nie znać zwyczajnie tego wzorca projektowego.

I tutaj pewnie nieraz nasi słuchacze mieli do czynienia właśnie z takimi uwagami od strony osób przeglądających, że może zastosowanie tego wzorca miałoby sens, że może tutaj spróbować to ugryźć za pomocą innego wzorca.

I to ma takie swoje dwie strony. Z jednej strony jest to okazja do nauki, to też nie ma co tutaj tego nie doceniać, że możemy w praktyce zauważyć czy być poinformowanym, że można coś było zrobić prościej, przejrzyściej, czyściej, ale z drugiej strony, tak jak powiedziałeś, często forsujemy te wzorce projektowe tylko dlatego, żeby one tam były, a de facto nie wnosi to nic więcej. Są alternatywy, z których można skorzystać, więc tak, nie próbujmy tutaj na siłę na code review zarówno jako autorzy, jak i reviewerzy walczyć o wzorce projektowe, bo nie zawsze to ma sens.

To tu jeszcze mała anegdotka w takim razie o code review. Pamiętam kiedyś jeszcze na początku swojej kariery zrobiłem jakiś pull request, po czym kolega mówi: a Łukasz, wiesz, co tutaj za wzorzec projektowy użyłeś? A ja mówię: no ale ja tu żadnego wzorca nie użyłem. No ale tutaj jest tam taki wzorzec i taki, i wymyśliłem wzorzec, którego po prostu nie znałem, ale udało się zaimplementować i wymyślić.

Można i tak.

Okej, no to wracając, kiedy nie używać tych wzorców? Myślę, że też nie zawsze ma to sens, żeby ich używać od samego początku, jak coś robimy. Zawsze starajmy się robić jak najprostszy kawałek kodu w pierwszej kolejności, a dopiero później pewnie nastąpi refaktoryzacja do tego wzorcu, jeśli będzie taka potrzeba. Oczywiście nie zawsze. My informatycy wiemy, że takie kwantyfikatory silne jak: zawsze, nigdy, wszyscy, nikt, to nigdy w przyrodzie nie występują. Mam nadzieję, że zauważyliście, co tu zrobiłem.

Okej, no to wracając, kiedy nie używać tych wzorców? Myślę, że też nie zawsze ma to sens, żeby ich używać od samego początku, jak coś robimy. Zawsze starajmy się robić jak najprostszy kawałek kodu w pierwszej kolejności, a dopiero później pewnie nastąpi refaktoryzacja do tego wzorcu, jeśli będzie taka potrzeba. Oczywiście nie zawsze. My informatycy wiemy, że takie kwantyfikatory silne jak: zawsze, nigdy, wszyscy, nikt, to nigdy w przyrodzie nie występują. Mam nadzieję, że zauważyliście, co tu zrobiłem.

👉 Czytaj dalej: https://porozmawiajmyoit.pl/poit-245-software-craftsmanship-wzorce-projektowe-hot-or-not/

--

--

Krzysztof Kempiński
kkempin’s dev blog

IT expert. Ruby on Rails/iOS/Elixir programmer. Blogger. Podcaster.