Temat Wzorców Projektowych budzi wiele emocji. Niektórzy są ich zagorzałymi fanami, inni podchodzą z pogardą twierdząc, że w rzeczywistym świecie są bezużyteczne.
Wzorce Projektowe są jedynie narzędziem, a emocjonalne podchodzenie do "młotka" jest po prostu nieracjonalne. Dlatego zaproponuję nieco inne podejście - kontekstowe.
Swoją drogą ciekawe, że podczas rozmów coraz częściej słyszę z ust wytrawnych programistów wyraz irytacji nad bezkontekstowym podejściem naszej branży do wszelkich technik, praktyk, metodyk, produktów, rozwiązań. Mówi się, że jesteśmy sterowani modą bardziej niż Mediolan lub Paryż;)
Odczuwa się silne zmęczenie marketingiem.
W swojej karierze programistycznej miałem okazję pracować nad systemami różnej klasy. Przez klasę rozumiem klasę problemów jakie stanowiły główne wyzwania. Ale to praca trenera i konsultanta dała mi dostęp do wglądu w spektrum klas problemów, w ilości jaką standardowo kolekcjonuje się w okolicach emerytury.
Piszę o tym aby przejść do kontekstu stosowalności Wzorców Projektowych. Z moich obserwacji wynika, że kontekst ten jest rozpięty na 2-wymiarach: wspomnianej już klasie problemu oraz w wymiarze osobowości (otrzemy się o aspekty psychologii programistów).
KONTEKST KLASY PROBLEMU
Jeżeli jesteśmy w kontekście aplikacji biznesowych, a nasza praca polega na implementowania kolejnych wymagań, to stoją przed nami wyzwania typu:
- okiełzanie nielogicznych wymagań
- modelowanie narzędzia dla biznesu (naszej aplikacji), który działa z natury procesowo
- tworzenie intuicyjnego GUI
- wpasowanie się w istniejącą bazę danych, która była projektowana przed III Wojną Mandżulską, w czasach gdy nikt jeszcze tak na prawdę nie rozumiał domeny.
W tym kontekście często nie potrzebujemy nawet używania technik OO - aczkolwiek programujemy
z użyciem obiektów (bo niby jak inaczej w mainstreamowych językach?).
Z szerokiego
wachlarza Wzorców Projektowych możemy posłużyć się w tym kontekście - w pewnych bardziej złożonych - przypadkach:
-
Strategią - jeżeli mamy odmiany tego samego zachowania/czynności biznesowej. Podejście promowane przez ten wzorzec staje się ostatnio modne za sprawą języków funkcyjnych. By czymże innym na poziomie syntaktycznym jest przekazanie obiektu implementującego interfejs z jedną metodą niż zwykłym przekazaniem funkcji na poziomie semantycznym?
-
Łańcuchem Odpowiedzialności - łańcuch zaczyna się nam opłacać gdy chcemy modelować podejmowanie decyzji o tym, który z wariantów logiki biznesowej chcemy wykonać. Opłaca się gdy spodziewamy się modyfikowania ilości wariantów.
-
Specyfikacją - pozwala na przejrzyste modelowanie złożonych reguł określających czy dany obiekt biznesowy powinien podlegać jakiemuś przetwarzaniu. Opłaca się gdy reguły są zawiłe i istnieją pomiędzy nimi zależności logiczne. Złożony wzorzec, że wystąpić kilka razy w całym kodzie.
-
Stanem - bardzo złożony wzorzec, może wystąpić raz, może dwa w średniej wielkości systemie. Pozwala na przejrzyste modelowanie maszyny stanów, dla obiektów biznesowych, które mają np różne statusy i w zależności od statusu a) mogą lub nie przechodzi w inne oraz b) inaczej się zachowują. Opłaca się gdy mamy wiele statusów i zawiła logikę sterującą zachowaniem zależnym od statusów.
-
Metodą Szablonową - prosty wzorzec, klasyka polimorfizmu, pozwala modelować różne warianty algorytmów biznesowych. Z czasem gdy sytuacja się komplikuje przestaje się opłacać i warto dokonać refaktoringu do Strategii.
-
Fasadą - trywialny wzorzec, który nie zasługuje na miano wzorca, ale wygodnie upraszcza to co najpierw skomplikowaliśmy;)
-
Dekoratorem - wprowadzenie dekoratora zaczyna się nam opłacać gdy chcemy !w runtime! (nie podczas programowania czy kompilacji) decydować o dodawaniu nowych zachowań. Bardzo silny, ale rzadko logika biznesowa daje się tak elegancko zamodelować.
Pomijam Singletona, który w większości przypadków jest antywzorcem
zabijającym testowalność. Poza tym jego istnienie w modelu biznesowym rzadko bywa sensowne.
O ile pojawienie się w aplikacji biznesowej wielu przypadków wykorzystania Strategii, Metody Szablonowej, Fasady jest normalnym zjawiskiem o o tyle duża ilość Łańcuchów, Dekoratorów czy Stanów wskazuje na overengineering i "chorobę wzorcową".
Pozostałe wzorce z katalogu nie mają zbyt dużej szansy na potencjalne pojawienie się w aplikacji biznesowej - po prostu służą do rozwiązywania problemów innych klas.
W aplikacjach biznesowych za to więcej pożytku niosą wzorce innego rodzaju:
- sposoby modelowania, oraz strategicznego modelowa z zestawu
Domain Driven Design
-
archetypy modeli biznesowych
- najlepsze praktyki odnośnie
Usability
Jeżeli natomiast jesteśmy w kontekście tworzenia oprogramowania klasy: platforma, framework, server, wysokowydajny dedykowany portal, oprogramowanie specjalistyczne typu: narzędzia do projektowania/komponowania, itp wówczas stajemy przed problemami zupełnie innej klasy:
- otwartość na rozbudowę z jednoczesną ochroną publicznego api przed zmianami core,
- wydajność, oszczędność pamięci,
- bezpieczeństwo,
- giętkość api,
- wyważenie ograniczeń
- itp.
Przeglądając kody źródłowe tego typu aplikacji możemy dostrzec wiele wystąpień wzorców lub struktur do nich podobny zmodyfikowanych z powodu pewnych intencji. Czasem są po prostu nazwane inaczej z powodu niewiedzy autora - ale ciekawe jest, że wpadł na pewne pomysły niezależnie, nie znając wzorca wcześniej.
Oprócz wspomnianych wcześniej wzorców opłacalne w tym kontekście
dodatkowo mogą być:
-
Builder - aby odseparować plany budowy obiektów od ostatecznego kształtu konstrukcji. Opłacalny gdy przewidujemy pojawianie się kolejnych "produktów"
-
Visitor - aby umożliwić użytkownikom api wprowadzanie nowych zachowań poprzez dodawanie swojego kodu zamiast modyfikowania biblioteki/frameworka. Double Dispach dla ubogich np. w celu otwarcia core na rozbudowę
-
Proxy - aby umozliwić model programistyczny w stylu Aspect Oriented
-
Mediator - śmietnik na chaos sieci współpracujących obiektów. Jeżeli musisz mieć chaos, to explicite ogranicz jego zakres.
-
Most - jeżeli masz niestabilny core i chcesz zaryzykować publikowanie stabilnego api
-
Prototyp - jeżeli chcesz fabrykować wiele klas i nie chcesz tworzyć analogicznej do nich, lustrzanej hierarchii fabryk.
-
Flyweight - jeżeli musisz mieć ogromną ilość obiektów, ale część ich pół możesz uwspólnić, ponieważ nie jest to ich zmienny stan - oszczędzasz pamięć.
Podając przykłady dla obu klas problemów chciałem pokazać, że po prostu inni programiści/projektanci/architekci mogą żyć w innym świecie. To że coś jest dla nas bezużytecznie, nie oznacza, je jest to bezużyteczne w ogólności.
Wrzucanie wszystkich programistów do jednego worka (najlepiej wspólnego worka z Informatykami;) powoduje utratę kontekstu a co za tym idzie rozmycie wymaganych do danego zadanie kompetencji.
Warto też zastanowić się nad klasami problemów jakie nas intrygują i rozwijać odpowiedni skillset - bez odpowiedniego poziomu kompetencji pewne klasy projektów będą dla nas zawsze zamknięte.
KONTEKST OSOBOWOŚCI
Chyba każdy programista przyzna, że zależy mu na zaprojektowaniu najprostszego rozwiązania. Być może to poszukiwanie prostoty jest tym, co przyciąga ludzi do programowania - no może za wyjątkiem robotników umysłowych napędzanych chęcią łatwego (hehe naiwni) zarobku.
Problem leży w postrzeganiu prostoty.
Niektórzy mówią, że jakieś podejście jest proste jeżeli można szybko zacząć się w tym orientować. I nie ważne, że później okaże się to pogmatwane w szczegółach. Ważne aby szybko zacząć "łapać" o co chodzi, a później - trudno, świat jest pogmatwany.
Inni mówią, że coś jest proste, jeżeli u swoich założeń ma dające się dokładnie zrozumieć fundamenty, które pozwalają wyobrazić sobie całe rozwiązanie mentalnie. Nie ważne, że może na początku trzeba zainwestować czas - dużo czasu - w zrozumienie pryncypiów i nowych rzeczy, które powierzchownie wydają się złożone. Jeżeli później okaże się, że było to proste, to mówią, że jest to proste.
Które podejście jest lepsze - jak zwykle, zależy to od kontekstu. W kontekście IT np. może zależeć od ograniczeń czasowych, czyli tego ile czasu możemy poświęcić. Innym ograniczeniem może być opłacalność w perspektywie czasu (czasem robimy eksperyment biznesowy i zobaczy jak się to rozwinie:). Dlatego w każdym przykładzie wzorca pisałem o tym kiedy może się nam opłacać wprowadzenie danej konstrukcji.
Strategia poznawcza, jaką przyjmuje nasz mózg w podejściu do prostoty (musi być proste od razu, musi być proste docelowo) wiąże się mocno z typem naszej osobowości.
- część z nas jest zorientowana na postrzeganie podobieństw, inni na postrzeganie różnic -
model meta-programów .
- część z nas jest otwarta na nowe doświadczania, inni są bardziej konserwatywni -
model Big 5.
- część z nas ma swój wewnętrzny świat, w którym modeluje postrzeganą rzeczywistość, inni są nastawieni na natychmiastowe działanie i niemal namacalne doświadczanie -
model MBTI
- część z nas żyje w przyszłości, w jakimś jej
modelu, inni żyją tu i teraz w
czasie.
MODEL DREYFUS
O modelu kompetencji Braci
Dreyfus pisałem już
kilkakrotnie. Tutaj przytoczę tylko poziom
Competent. Rozwijając jakąś umiejętność, na tym poziomie w naturalny sposób zaczynamy szukać najlepszych praktyk, wzorców (nomen omen). Tak więc naturalne jest, że rozwijając kompetencję pod tytułem "Programowanie/Projektowanie OO" w pewnym momencie zaczniemy szukać wzorców.
Na kolejnych etapach rozwoju tej kompetencji będziemy zadawać pytanie, kwestionować, szukać szerzej. Jednak na trzecim poziomie (Competent) katalog wzorców daje dużego kopa i pozwala po prostu zoptymalizować proces uczenia się. Jak powiedział
Jim Copelin, z czasem odrzucasz "boczne kółka od swego rowerka" i przestajesz mówić o wzorcach, po prostu intuicyjnie robisz to co należy.
//==============================================
Czasem można spotkać głosy, że wzorce projektowe są "zbyt akademickie". Hmm moim zdaniem wręcz odwrotnie. Do katalogu wzorców nie trafiają żądne rozwiązania, które nie są odkryte i przedyskutowane przez community praktyków. Oczywiście, stosując zbyt wyrafinowany wzorzec do zbyt błahego problemu będziemy odczuwać przerost formy nad treścią. Ale wówczas powodem jest nieumiejętne użycie w nieodpowiednim kontekście - czyli jego niezrozumienie.
Aby nabrać wyobrażenia o tym, co to znaczy "akademickie" podejście do OO należy zapoznać się z
tym tekstem.