Jakie wzorce projektowe są najgorsze lub najściślej zdefiniowane? [Zamknięte]

28

W każdym projekcie programistycznym menedżerowie z doświadczeniem w programowaniu starają się zabłysnąć, gdy zalecają pewne wzorce projektowe dla twojego projektu. Lubię wzorce projektowe, gdy mają sens lub gdy potrzebujesz skalowalnego rozwiązania. Na przykład korzystałem z wzorców proxy, obserwatorów i wzorców poleceń i robię to codziennie. Ale naprawdę waham się użyć powiedzenia wzorca fabrycznego, jeśli istnieje tylko jeden sposób na utworzenie obiektu, ponieważ fabryka może ułatwić to w przyszłości, ale komplikuje kod i jest czystym kosztem.

Tak więc moje pytanie dotyczy mojej przyszłej kariery i mojej odpowiedzi na typy menedżerów rzucające losowe nazwy wzorców wokół:

Jakich wzorów projektowych użyłeś, które ogólnie cię odrzuciły? Jakie są najgorsze wzorce projektowe , które należy wziąć pod uwagę, z wyjątkiem jednej sytuacji, w której mają one sens (czytaj: które wzorce projektowe są bardzo wąsko zdefiniowane)? (To tak, jak szukałem negatywnych recenzji ogólnie dobrego produktu Amazon, aby zobaczyć, co najbardziej wkurzyło ludzi w używaniu wzorów projektowych.) Nie mówię tu o Anty-Wzorach, ale o Wzorach, które zwykle są uważane za „dobre” wzory.

Edycja: Jak niektórzy odpowiedzieli, problemem jest najczęściej to, że wzorce nie są „złe”, ale „źle użyte”. Jeśli znasz wzory, które są często niewłaściwie używane lub nawet trudne w użyciu, pasują również jako odpowiedź.

Akku
źródło
Większość wzorów ułatwia przyszłe zmiany na niektórych osiach zmian, ale mogą utrudniać zmiany na innych osiach zmian. Grupa czterech książek jest szczególnie dobra w mówieniu, kiedy ma zastosowanie wzorzec. Wiele kolejnych książek o wzorach nie ma tego punktu. Weźmy wzór gościa jako przykład. Ułatwia dodawanie nowych algorytmów przechodzenia przez drzewo, ale utrudnia dodawanie nowych rodzajów węzłów do drzewa. Pozwala także, aby algorytmy przechodzenia znajdowały się na wyższej warstwie niż drzewo. Musisz rozważyć, która oś zmiany jest najmniej stabilna, i zaprojektować, aby zmiany wzdłuż tej osi były łatwe.
Theodore Norvell,
Wszystkie z książki „Gang of Four”.
Miles Rout

Odpowiedzi:

40

Nie wierzę w złe wzorce, wierzę, że wzorce można źle zastosować!

  • IMHO singleton jest najbardziej nadużywanym i niewłaściwie stosowanym wzorcem. Wydaje się, że ludzie chorują na singletony i zaczynają dostrzegać możliwości singletonów na całym świecie bez rozważania alternatyw.
  • Wzorzec odwiedzających IMHO ma najbardziej wąskie zastosowanie i prawie nigdy dodatkowa złożoność nie będzie uzasadniona. Dobry plik pdf można znaleźć tutaj . Naprawdę tylko wtedy, gdy masz strukturę danych, o której wiesz, że zostanie przemierzona podczas wykonywania różnych operacji na strukturze danych bez znajomości wszystkich sposobów z wyprzedzeniem, daj wzorzec odwiedzającym szansę walki. Jest ładna :)

W tej odpowiedzi wziąłem pod uwagę tylko wzorce GOF. Nie znam wszystkich możliwych wzorców wystarczająco dobrze, aby je również uwzględnić.

KeesDijk
źródło
Widzę bardzo mało zastosowań dla odwiedzających. Singletony ... nie zaczynaj mnie. Jeśli sytuacja nie jest idealna dla jednego, nie używaj go.
Michael K
1
Może być bardzo mało zastosowań dla Odwiedzającego, ale gdy jest, z pewnością rozwiązuje problemy. Rozumiem, że Vistor jest niezbędny dla LINQ.
quentin-starin
12
Wzorzec gościa ma kluczowe znaczenie dla zmniejszenia (lub wyeliminowania) cykliczności złożoności w programie. Za każdym razem, gdy masz drzewo if / else lub instrukcję switch, istnieje duże prawdopodobieństwo, że gość może je zastąpić, oferując gwarantowane wykonanie i sprawdzanie czasu kompilacji. Gość jest jednym z najpotężniejszych wzorców, jakie znam, i używamy go regularnie z doskonałym skutkiem. Sprawia, że ​​testowanie jest również snem.
Les Hazlewood,
@LesHazlewood Czy zatem gość nie jest jedynie obejściem nieodpowiednich języków programowania? Języki podobne do ML (Haskell, SML, OCaml itp.) Mają algebraiczne typy danych („unia na sterydach”) i dopasowywanie wzorców („włączanie sterydów”), które wytwarzają prostszy kod niż gość, ale w pełni sprawdzone przez kompilator. W porównaniu z gościem nie masz wielu metod, których stanem współdziałania musisz zarządzać ręcznie za pomocą właściwości obiektu. W językach podobnych do ML wszystkie rozróżnienia wielkości liter muszą być kompletne, w przeciwnym razie nie zostaną skompilowane.
vog
14

Oprócz Singletona i Odwiedzającego, o których wspominali już inni autorzy, nie znam „znanych” wzorów. Największe problemy IMHO nie wynikają z tego, że określony wzorzec projektowy jest „zły”, ale raczej z tego, że programiści stosują wzorce zbyt chętnie.

Prawie wszyscy przechodzą fazę „gorączki wzorcowej” podczas poznawania wzorców. Myśląc, że wzory są najlepsze od czasu krojonego chleba, początkowo próbuje się je stosować, gdy tylko widzi taką możliwość. Powoduje to, że kod zostaje zakopany pod wzorami, przy czym same wzorce już nie pomagają, po prostu utrudniają zrozumienie i utrzymanie kodu na dłuższą metę.

W końcu większość z nas przechodzi przez tę fazę i zaczyna uczyć się, jak używać wzorców do rozwiązywania prawdziwych problemów, a nie dla nich samych. Wzorce mają swoją cenę, co jest dodatkową złożonością, a zastosowanie dowolnego określonego wzorca jest uzasadnione tylko wtedy, gdy zwraca dodatkową złożoność, pomagając uprościć inną część systemu, dzięki czemu kod / konfiguracja ogólnie jest łatwiejsza do zrozumienia i utrzymania. Jeśli tak nie jest, często lepiej jest trzymać się z dala od wzorów, pozostając przy najprostszym rozwiązaniu, które może działać.

Péter Török
źródło
Absolutnie. Wzory nie są dobre ani złe, są dobrze stosowane lub niewłaściwie stosowane.
Wolę uczyć ludzi tak, jak się nauczyłem: OO, najpierw rozumiem, jak odnoszą się przedmioty, a potem uczę się nazw wzorców. Zbyt łatwo jest myśleć w kategoriach wzorców niż tego, co należy zrobić. Są narzędziem komunikacji.
Michael K
Wzory są środkiem komunikacji, a nie nakazową listą. Jeśli zaczynasz z myślą o pewnym wzorze, być może niewłaściwie go stosujesz. Jeśli znajdziesz jeden lub kilka wskazówek w swoim projekcie, katalogi wzorów pomogą ci zrozumieć, czego jeszcze możesz potrzebować.
Rob Crawford
14

Mam zamiar wyjść tutaj na kończynę i zasugerować nadużywanie dziedziczenia. Zdecydowanie najbardziej odpowiedni w językach bez solidnej obsługi polimorfizmu w czasie kompilacji, takich jak Java. Dziedziczenie w czasie wykonywania jest narzędziem, a nie jakimś cudem dla jednej cechy.

Inni ludzie już wyrazili swoją podobną do mojej osobistej nienawiści do Singletonów, więc nie zamierzam tutaj o tym mówić.

DeadMG
źródło
10

Singel. Jest to wzorzec GOF, który jest obecnie częściej nazywany anty-wzorem. Jednym z powodów jest to, że Singleton utrudnia testowanie kodu.

SiberianGuy
źródło
4
Istnieje wiele fundamentalnych wad we wzorze singletona, większość dobrze ilustruje ten artykuł Steve Yegge - Singleton uważa się za
głupca
Slomojo: Niezły artykuł. Odtąd będę go nazywać „wzorem prostokąta”:-)
Nikt
2
Tak, ponieważ jakiś głupiec niewłaściwie używa wzoru i całkowicie tęskni za łodzią na temat tego, o co chodzi w OO (sądząc po wszystkich klasach Menedżera, które wymyślił), Oczywiście to wina tego wzoru, a nie deweloperów.
Dunk
Dlaczego wszyscy kojarzą wspólną (i kłopotliwą) implementację Singleton ze wzorem Singleton? Jedno jest prawie zawsze złe, drugie nie.
quentin-starin
1
@qes> Singleton wiąże się z ważnymi problemami z implementacją (szczególnie z wątkami). To już jest zły punkt. Ale dowiesz się również, że singleton jest wzorcem na temat tego, jak klasa jest pozwana, a nie jak to działa. Sposób użycia klasy powinien być obsługiwany przez kod za pomocą klasy, więc Singleton stanowi przerwanie separacji problemów.
deadalnix
7

Jeśli znasz wzory, które są często niewłaściwie używane lub nawet trudne w użyciu, pasują również jako odpowiedź.

Po wzorzec MVVM dla WPF zbyt ściśle, jak wskazano na przykład przez to pytanie . Niektóre osoby starają się postępować zgodnie z wytyczną, że żaden kod nie powinien być umieszczany w kodzie zbyt ściśle i wymyślają wszelkiego rodzaju egzotyczne hacki.

I oczywiście MVVM jest trudne jak diabli i po prostu nie jest tego warte w przypadku małych projektów krótkoterminowych.

Dr WPF napisał o tym ironiczny post w swoim artykule MV-poo .

Steven Jeuris
źródło
@Akku: Powinieneś oczywiście wiedzieć, jak go używać, abyś mógł zdecydować, czy jest odpowiedni dla twojego projektu. Tak, jest to niezbędne do rozwoju WPF i bardzo przydatne.
Steven Jeuris,
Jednym z problemów jest to, że ludzie źle rozumieją wzór MVVM. To nie jest „trudne jak diabli”. Ludzie robią to w ten sposób, myśląc, że wszystkie inne wzorce, takie jak Wzorzec Dowodzenia i Wzorzec Mediatora, są jego częścią. Moim zdaniem MVVM jest jednym z najprostszych wzorów. Zgadzam się, że podążanie za czymkolwiek do t jest po prostu głupie.
BK
5

Niektóre wzorce w książce GOF są specyficzne dla C ++, w tym sensie, że są mniej przydatne w językach z odbiciem, np. Wzorzec prototypowy jest mniej znaczący w Javie.

Uważam wzorzec interpretera za „wąski”. Musisz mieć ogólny problem, który wart jest opracowania ogólnego rozwiązania problemu. Działa tylko w przypadku specjalnych problemów, dla których możesz wymyślić język, zdefiniować gramatykę i napisać tłumacza. Przypadki problemowe powinny być reprezentowane jako zdanie w gramatyce. Nie sądzę, że często zdarza się takie sytuacje.

Karl
źródło
1
większość GOF ma zastosowanie tylko do OOP opartych na klasach statycznych. choć trochę oddalają się od tego rodzaju języków, a książka staje się tylko anegdotą rozrywkową.
Javier
5

Ten, którego najczęściej żałuję (choć nie najbardziej gwałtownie): kiedy powinienem właśnie utworzyć funkcję, ale wdrożyłem rozwiązanie OOP.

C SD
źródło
1
Czemu? Co sprawiło, że tego żałowałeś? Rozwiń swoją odpowiedź i dodaj swoje wrażenia.
Walter
Rzeczywiście, myślę, że klasa z lokalnymi zmiennymi i jasnymi metodami jest O wiele łatwiejsza do ponownego użycia niż pojedyncza funkcja 200 linii, którą można ponownie zastosować tylko za pomocą kopiowania wklej, a wtedy nie ma tylko jednego miejsca, które mogłoby wyglądać brzydko i niezrozumiale.
Akku
2
KISS sugeruje, że najpierw musisz ustawić funkcję, a następnie zmienić klasę w razie potrzeby.
Eva
5

Fabryka. Widziałem kod implementujący go, który tworzy tylko jeden typ. To całkowicie bezużyteczny kod IMO. Nie pomaga to, że wiele przykładów online jest całkowicie wymyślonych. Fabryka pizzy?

Być może fabryka jest łatwiejsza do przetestowania z powodu wstrzyknięcia zależności. Ale dodanie tego kodu, gdy go nie potrzebujesz, jest dla mnie bezcelowe, a argument testowy znika, gdy możesz użyć fałszywych frameworków, takich jak JMockit. Im łatwiej można stworzyć program, tym lepiej. Fabryki naprawdę mają sens tylko przy większej liczbie typów (przez większą, mam na myśli przynajmniej więcej niż 2).

Michael K.
źródło
Tak, fabryka pizzy, dzięki za Head First Design Pattern ~
Niing
2

Singel

Zgadzam się z innymi w sprawie Singletona. Nie dlatego, że nigdy nie powinieneś ich używać, tylko że powinno to być ograniczone do bardzo niewielu przypadków. Są one często używane jako leniwe globale.

Bezpieczeństwo wątków to jeden problem z singletonami. Obsługa wyjątków jest inna - jeśli singleton nie utworzy się poprawnie - nie zawsze wiesz, czy możesz bezpiecznie uchwycić błąd, szczególnie jeśli był to jeden z tych obiektów utworzonych „przed głównym”. A potem jest kwestia późniejszego sprzątania.

Wolę używać jednego singletona, a wszystkie inne „niedoszłe” singletony „subskrybują” twoje. Moim najczęstszym zastosowaniem singletonu jest obsługa zdarzenia „krzyczeć”: po prostu „transmitujesz na cały świat”, że wydarzenie miało miejsce, i każdy, kto go słucha, to zrobi. W ten sposób oddzielasz wydarzenia, które faktycznie mają miejsce, od tego, co ich słucha. (Rejestrowanie, sygnały itp.)

Gość

Brzydką rzeczą, którą o tym znajduję, poza tym, że programiści nie mogą wymyślić znaczących nazw i po prostu wywołują metody visit (), jest to, że dodaje rozszerzalność w jednym kierunku, a jednocześnie usuwa w innym, tj. Dodaje dodatkową funkcjonalność, ale ogranicza liczba obiektów, jakie odwiedzający muszą wiedzieć o wszystkich typach obiektów, które mogą odwiedzać.

Możliwe jest, choć niechlujne, zezwolenie na przedłużenie w obu kierunkach, ale nie wykorzystuje to całkowicie wzoru odwiedzającego w jego zwykłej formie. Najczęstszą aplikacją do tego jest drukowanie obiektów: istnieją różne sposoby drukowania obiektów i różne obiekty, które należy wydrukować. Powinieneś być w stanie rozszerzyć to w obu kierunkach. (Drukowanie oznacza dowolne przekształcanie obiektów w strumień: przechowywanie w pliku / zapisywanie w konsoli / GUI ... itp.).

(Uwaga: nie należy mylić tego z architekturą widoku dokumentu, która jest nieco innym wzorcem).

Dojną krową
źródło
2
Twoje rozwiązanie wykorzystuje stary argument, który oddziela rzeczy. W szczególności publikujesz wydarzenie, a jakiś inny facet obsługuje je i rejestruje. To dobrze, ponieważ wszyscy są oddzieleni! ŹLE! Robiłem to, jaki to był królewski ból. Uświadomiłem sobie, że jeśli chcę, aby coś było rejestrowane, chcę wyraźnie powiedzieć, aby zalogować to dokładnie tutaj, właśnie teraz, w kodzie w miejscu, w którym to się wydarzyło. Nie pozwól, aby jakiś inny obiekt zorientował się, co powinno być rejestrowane, z możliwymi innymi zdarzeniami wykrytymi przez inne programy obsługi, nawet jeśli w ogóle są rejestrowane. To nic innego jak zawiły projekt.
Dunk
2

Myślę, że problem z niektórymi bardziej złożonymi wzorcami polega na tym, że jest ich tak wiele, że tracą one swoją wartość jako urządzenia komunikacyjne.

Najgorszym przestępcą, o jakim mogę myśleć w tej kategorii, jest wzór MVC. Nawet jeśli zignorujemy MVP, jest tak wiele odmian ról każdego z tych elementów, że musisz spędzić godzinę w każdym nowym systemie, zastanawiając się, gdzie leżą granice.

Uri
źródło
Uważam również, że MVC powinno być używane wszędzie, ale nie powinno być wszędzie wdrażane w ten sam sposób. I wiele osób tego nie rozumie. Kiedy po raz pierwszy chciałem go użyć, stworzyłem trzy klasy o nazwie Model, Widok (formularz systemu Windows) i Kontroler. To był bałagan, ponieważ formularze nie zostały stworzone dla MVC.
Akku
1

Nie ma złych wzorów, tylko źli ludzie.

Wolałbym odziedziczyć łatwo czytelny kod, który robi coś wyraźnego, ale jest trochę gadatliwy lub nie (kolejka złej muzyki villian) wielokrotnego użytku (łapanie oddechu!) Niż jakaś miszmasz InheritAbstractTemplateFaucetSink<Kitchen>.

Kod wielokrotnego użytku jest świetny! Możliwe, że nie piszesz kodu, który zostanie ponownie użyty, lub ponowne napisanie podobnej logiki dla innej aplikacji zajmie Ci mniej czasu niż szalona próba ponownego użycia kodu innej aplikacji.

Aby dalej czytać, należy otworzyć część kodu C w rozsądnych implementacjach nagłówków posix lub clibs i odtworzyć wzór. Ten kod został napisany przez jednych z najmądrzejszych i najbardziej oddanych programistów na świecie. Czy wiesz, ile abstrakcyjnych wzorów fabrycznych zobaczysz? ... ŻADEN!. Jeszcze większe szanse są, jeśli zrozumiesz inne części tego, co się dzieje, znajdziesz logikę bardzo łatwą do zrozumienia i śledzenia.

Chodzi mi o to, że większość „wzorów” nie została stworzona w celu ulepszenia kodu, ale zostały stworzone do sprzedaży książek i oprogramowania do modelowania. Jeśli jesteś dobry w programowaniu, prawdopodobnie unikniesz większości z nich i napiszesz przejrzysty, zwięzły i sprytnie zaprojektowany kod, który rozwiąże twój problem. Gdy pojawi się kolejny problem, napiszesz przejrzysty, zwięzły, sprytnie zaprojektowany kod, aby go rozwiązać. Jeśli twoim celem jest napisanie mniej kodu, nie sądzę, że nie jesteś programistą. Uwielbiam pisać kod i chcę pisać tak dużo, jak to możliwe. Kiedy ponownie piszę coś, co już napisałem, robię to dziesiątki razy szybciej i pozbywam się wszystkich rzeczy, z których nie byłem zadowolony za pierwszym razem.

Dzięki temu zostawię ci prawdopodobnie najlepszy (odpowiedni) cytat z informatyki.

Istnieją dwa sposoby konstruowania projektu oprogramowania: Jednym ze sposobów jest uczynienie go tak prostym, aby oczywiście nie było braków, a drugim sposobem jest uczynienie go tak skomplikowanym, aby nie było oczywistych braków. Pierwsza metoda jest znacznie trudniejsza .

  • Tony Hoare (wynalazca Quicksort, ojciec nowoczesnego projektu systemu operacyjnego, twórca logiki Hoare i laureat nagrody Turinga)
nsfyn55
źródło
0

Zdecydowanie zgadzam się, że jest czas na większość wzorów i że możesz nadużywać wiele wzorów. Wiem, że najbardziej nadużywałem w przeszłości wzór szablonu abstrakcyjnego. W pełnym zakresie jest znany jako formularze internetowe ASP.NET.

Wyatt Barnett
źródło