Czy istnieją jakieś wzorce projektowe, które są niepotrzebne w dynamicznych językach, takich jak Python?

98

Zacząłem czytać wzornik projektowy autorstwa GoF. Niektóre wzory wydają się bardzo podobne, z niewielkimi różnicami pojęciowymi.

Czy uważasz, że z wielu wzorców niektóre są niepotrzebne w dynamicznym języku, takim jak Python (np. Ponieważ są one zastąpione przez funkcję dynamiczną)?

Gerenuk
źródło
1
To interesujące pytanie, ponieważ sugeruje, że wybór języka może skutecznie zastąpić konstrukcje kodu.
joshin4colours
3
Nie odpowiedź, ale trafna - myślałem, że wzorce projektowe GoF są tak samo odpowiednie dla niektórych ogólnych zasad, które można z nich wydestylować, jak dla konkretnych wzorców. Nie mam na myśli idei wzorca (choć z pewnością jest to znaczące), ale bardziej pozwolenie na używanie klas w określony sposób, które naruszają naiwne zasady OOP. Na przykład istnieje wiele wzorów, w których „kształt” dość wyraźnie „nie rysuje się” lub przynajmniej przekazuje pewien aspekt zadania do innego obiektu. Myślę, że lekcja jest ważna w każdym języku, który obsługuje OOP.
Steve314,
Bardzo interesujące pytanie. Chciałbym móc +5 zamiast +1.
MathAttack
1
Rzuć okiem na Brakujące wzory językowe i brakujące wzory językowe w c2. To nawet nie jest kwestia „dynamicznego języka”. Najprostszym przykładem jest wzorzec iteratora, który jest trywialny w Pythonie, Perlu (a nawet Javie - nie dynamiczny).

Odpowiedzi:

92

Peter Norvig pokazuje, że 16 z 23 wzorców projektowych znalezionych w książce GOF jest niewidocznych lub prostszych w dynamicznych językach (skupia się na Lisp i Dylan).

Odkąd wspomniałeś o Pythonie, Alex Martelli ma przyjemną prezentację na ten temat. Powiązany również z Pythonem, jest ładny post na blogu pokazujący sześć wzorców projektowych w idiomatycznym Pythonie .

Prowadzę również repozytorium github z implementacjami (przez innych ludzi) najpopularniejszych wzorców projektowych w Pythonie .

sakisk
źródło
Wspaniały! To byłoby miejsce na odpowiedź :) Żałuję, że wszyscy nie zrozumieli tak wyraźnie pytania.
Gerenuk,
2
Według Norviga 2 z 16 (Interpreter i Iterator) są „albo niewidoczne, albo prostsze” z powodu makr (których Python nie ma).
mjs
1
nie jest dla mnie jasne, że wszystkie te wzorce nie są potrzebne, ponieważ seplenie jest dynamiczne, ale raczej z powodu innych cech, takich jak silny język funkcjonalny
jk.
@mjs Iterators to wbudowana funkcja Pythona.
sakisk
1
Ten wielki odpowiedź może być nawet nieznacznie poprawić zmieniając nieco bezsensowne tytuły linku pokazuje , prezentacji i repozytorium - są one znacznie lepiej niż tutaj , ale wiesz ... :-)
Wilk
59

Nie są wymagane żadne wzory projektowe. W dowolnym języku

Często napotykam dużo kodu napisanego przez ludzi, którzy czytają wzorce projektowe, a potem sądzą, że powinni z nich korzystać wszędzie. W rezultacie rzeczywisty kod zostaje zakopany pod mnóstwem interfejsów, opakowań i warstw i jest dość trudny do odczytania. To złe podejście do wzorców projektowych.

Wzory projektowe istnieją, dzięki czemu masz repertuar przydatnych idiomów pod ręką, gdy natrafisz na problem. Ale nigdy nie powinieneś stosować żadnego wzoru przed zidentyfikowaniem problemu. Niech to będzie proste Głupota zawsze powinna być nadrzędną zasadą rządzącą.

Pomaga również myśleć o wzorcach projektowych jako o koncepcji do myślenia o problemie, a nie o konkretnym kodzie wzorcowym do napisania. I w dużej mierze z podstawową metodą obejścia Javy bez wolnych funkcji i standardowych obiektów funkcji, których używasz w większości innych języków, które je mają (takich jak Python, C #, C ++ itp.).

Mogę powiedzieć, że mam wzorzec odwiedzających, ale w każdym języku z funkcjami pierwszej klasy będzie to funkcja pełniąca funkcję. Zamiast klasy fabrycznej zwykle mam tylko funkcję fabryczną. Mógłbym powiedzieć, że mam interfejs, ale to tylko kilka metod oznaczonych komentarzami, ponieważ nie byłoby żadnej innej implementacji (oczywiście w Pythonie interfejs zawsze jest tylko komentarzem, ponieważ jest napisany kaczką). Nadal mówię o kodzie jako o użyciu wzorca, ponieważ jest to przydatny sposób, aby o nim pomyśleć, ale tak naprawdę nie wpisuj wszystkich rzeczy, dopóki naprawdę go nie potrzebuję.

Naucz się wszystkich wzorców jako pojęć . I zapomnij o konkretnych implementacjach. Implementacja różni się i powinna się różnić w świecie rzeczywistym, nawet w Javie.

Jan Hudec
źródło
28
Twoje oświadczenie wstępne jest wyjątkowo uproszczone. Prawdą jest, że wzory mają swój koszt, więc nie należy ich używać na ślepo, tylko ze względu na to. Ale we właściwym miejscu mogą być świetną pomocą. I tak, są one specyficzne dla języka - niektóre wzorce są niepotrzebne w niektórych językach, ponieważ sam język obsługuje lepsze podejście. Ale wciąż jest to dość dalekie od twojego początkowego roszczenia.
Péter Török
2
Btw Visitor nie jest całkowicie zastąpiony przez funkcje wyższego rzędu - jest to rozwiązanie do implementacji podwójnej wysyłki w języku, który nie obsługuje go natywnie (np. C # i C ++). (I rzeczywiście należy go używać bardzo oszczędnie - uważam go za jeden z najbardziej tajemniczych i kosztownych wzorów, którego użycie jest IMHO, tak trudno uzasadnić, że sam nigdy go nie używałem.)
Péter Török
14
Cóż, nigdy nie potrzebujesz wzoru. Potrzebujesz rozwiązania problemu . Jeśli nie znasz żadnego wzoru, nadal możesz go rozwiązać, to zajmie więcej myślenia i możesz wymyślić rozwiązanie, które pasuje do jakiegoś wzoru lub takiego, który nie. Znajomość wzorów ułatwia to.
Jan Hudec
3
@Gerenuk: Tak, ale chodzi o to, że wzorce nie są specyficzne dla języka, są dla twojej głowy. Często okazuje się, że niektóre wzorce są realizowane znacznie łatwiej i przy użyciu różnych narzędzi w Pythonie, ale zwykle istnieje ta sama koncepcja.
Jan Hudec
4
@ PéterTörök: Odwiedzający nie jest zastępowany przez nic. Chodzi o to, że ta sama koncepcja może być wdrożona przy użyciu różnych narzędzi w różnych przypadkach, ale nadal uważam, że to ten sam wzór.
Jan Hudec
13

Abstrakcyjny wzorzec fabryczny nie jest konieczny w języku pisanym kaczką, takim jak Python, ponieważ jest praktycznie wbudowany w ten język.

vartec
źródło
10
nadal potrzebujesz różnych fabryk. Po prostu nie potrzebujesz definicji interfejsu.
Stefano Borini,
1
Jeśli masz zajęcia, masz już fabrykę. Klasy są pierwszorzędnymi obiektami i można je wszędzie przekazywać i po prostu wywoływać, aby utworzyć obiekt (w przeciwieństwie do Java). Nie musisz tworzyć niczego innego. Jeśli chcesz czegoś, co nie jest domyślnym konstruktorem, po prostu stwórz pewnego rodzaju lambda / callable, który w jakiś sposób otoczy konstruktor.
spookylukey
13

Jedyne, co przychodzi na myśl, to wzór Singleton.

Ponieważ Python nie zmusza Cię do używania klas do wszystkiego , możesz zamiast tego użyć globalnej struktury danych. Ta globalna struktura danych mogłaby być zarządzana przez instancję, ale nie musisz kontrolować instancji tej klasy, po prostu stwórz instancję podczas importu i pozostaw ją w tym miejscu.

Przeważnie Singletony w pythonie są zastępowane modułem. Moduły w pythonie są ze swej natury Singletonami; interpreter Pythona tworzy je tylko raz.

Wszystkie inne wzorce w Design Patters, których użyłem w Pythonie w tym samym czasie, a przykłady ich znajdziesz w standardowej bibliotece Pythona i w samym Pythonie.

Martijn Pieters
źródło
2
Czy nie jest to obecnie anty-wzór?
Den
16
Singleton jest antypatternem . We wszystkich językach Został stworzony, aby rozwiązać kilka niezwiązanych ze sobą problemów i nie jest dobrym rozwiązaniem dla żadnego z nich (zauważ, że nawet Java ma statyczne elementy, które istnieją raz na klasę, więc nie potrzebujesz do tego instancji).
Jan Hudec
1
W Pythonie nigdy się tym nie przejmowaliśmy, ponieważ nigdy nie było problemu do rozwiązania.
Martijn Pieters
1
„Python nie zmusza cię do używania obiektów do wszystkiego” Nieprawda. To po prostu nie jest wstrętne jak w Javie, ale w Pythonie wszystko jest przedmiotem. Nawet moduł jest obiektem.
vartec
3
@Darthfett: Jestem w pełni świadomy tego, jak lendziała; Guido dokonał tutaj wyraźnego wyboru . Chodzi mi o to, aby pokazać, że Python nie jest czystym językiem OOP; jest to język pragmatyczny. Lubię to w ten sposób.
Martijn Pieters
8

Wzory projektowe są dla programisty, a nie dla języka. Programiści zwykle używają wzorców, które pomagają im zrozumieć obecny problem. Żaden wzorzec projektowy nie jest absolutnie konieczny, ale może być przydatny, aby uprościć to, co próbujesz zrobić.

Python, a w szczególności pisanie kaczek, kończy wiele popularnych wzorców i praktyk, a wiele ograniczeń narzuconych przez niektóre wzorce (prywatność, niezmienność itp.) Obowiązuje tylko w takim stopniu, w jakim programista zgadza się ich nie łamać . Ale nadal, one nie działają tak długo, jak programista odgrywa czas. Drzwi są nadal drzwiami, nawet jeśli są otoczone wyobrażonymi ścianami.

Python jest uważany za język „wielu paradygmatów”; możesz użyć dowolnych wzorów. To celowe. Zapewnia na przykład złożone hierarchie klas, nawet jeśli są one całkowicie niepotrzebne i nieco sztuczne. Ale dla niektórych osób ta abstrakcja jest pomocna. Nie dlatego, że wymaga tego problem, ale dlatego, że programista tego wymaga. Więc proszę bardzo.

tylerl
źródło
To z pewnością interesujące. Więc jakie wzorce w szczególności masz na myśli, że można zapomnieć, ponieważ istnieją lepsze sposoby w Pythonie?
Gerenuk
4

Oryginalna książka „Wzory projektowe” udokumentowała i wymieniła niektóre popularne idiomy przydatne w imperatywnych, zorientowanych obiektowo językach, takich jak C ++ i Smalltalk. Ale Smalltalk jest językiem dynamicznie pisanym, więc nie może być kwestią dynamiki.

Jednak odpowiedź na twoje pytanie brzmi „tak”: niektóre z tych wzorców projektowych nie będą miały znaczenia dla współczesnych języków dynamicznie typowanych. Mówiąc bardziej ogólnie, nie będzie różne wzorce projektowe w różnych językach, zwłaszcza w różnych rodzajów języków.

Powtórzmy: „wzorzec projektowy” to po prostu nazwa idiomu programistycznego: wspólne rozwiązanie często spotykanego problemu. Różne języki wymagają różnych idiomów, ponieważ problem dla jednego języka może być trywialny dla innego. W tym sensie wzorce projektowe wskazują na słabości języków, których dotyczą.

Możesz więc szukać innych funkcji, które zwiększą możliwości współczesnych języków dynamicznych (lub starożytnych, takich jak Lisp), co sprawi, że niektóre z tych klasycznych wzorów nie będą miały znaczenia.

nadchodząca burza
źródło
1

Wzory projektowe to sposoby rozwiązywania określonych problemów. Jeśli problem nie zostanie spełniony, wzorzec rozwiązania go nie ma zastosowania.

Ludzie starają się dostosowywać wzorce projektowe wszędzie, tak jakby najlepszą praktyką było posiadanie wzorców projektowych w projekcie. To jest na odwrót. Wystąpił problem, który można rozwiązać za pomocą wzoru fabrycznego? Chłodny. Dostosuj to. Nie sprawdzaj swojego kodu i nie próbuj znaleźć odpowiedniego miejsca na wdrożenie singletona (lub fabryki, fasady lub cokolwiek ...).

Być może Python ma własne wzorce projektowe niedostępne dla ludzi Java i .NET (z powodu natury tych języków)?

Andrzej Bobak
źródło
1

Powiedziałbym, że wzorce zawsze zależą od języka. To, że większość wzorców Pythona wygląda tak, jak te zdefiniowane w GoF, to z powodu OOP Pythona, że ​​powiedzenie, że OOP nie jest podobne do OOP (żadne dwa języki nie definiują obiektów i manipulowania nimi w 100%).

Nie ma więc wątpliwości, że niektóre wzorce nie będą miały zastosowania „tak jak są”, niektóre mogą nie mieć sensu, a niektóre wzorce mogą mieć znaczenie tylko dla Pythona.

Aby wrócić dokładnie na twoje pytanie: Wzory są konieczne tylko wtedy, gdy ich potrzebujesz . Nie musisz ich używać, jeśli nie są potrzebne (jak powiedział już Jan Hudec).

Ponadto istnieje znacznie więcej wzorów niż te wymienione w GoF. Zobacz w wikipedii inne wzory

estani
źródło