Wiele osób wydaje się zgadzać, że wzorzec Singleton ma szereg wad, a niektórzy nawet sugerują całkowite jego unikanie. Tutaj jest doskonała dyskusja . Wszelkie uwagi dotyczące wzorca Singleton prosimy kierować do tego pytania.
Moje pytanie : czy istnieją inne wzorce projektowe, których należy unikać lub których należy używać z wielką ostrożnością?
design-patterns
anti-patterns
Brian Rasmussen
źródło
źródło
Odpowiedzi:
Wzory są złożone
Wszystkie wzorce projektowe należy stosować ostrożnie. Moim zdaniem powinieneś dokonać refaktoryzacji w kierunku wzorców, gdy istnieje ważny powód, aby to zrobić, zamiast natychmiast wdrażać wzorzec. Ogólny problem z używaniem wzorców polega na tym, że dodają one złożoności. Nadużywanie wzorców utrudnia dalsze rozwijanie i utrzymywanie danej aplikacji lub systemu.
W większości przypadków istnieje proste rozwiązanie i nie ma potrzeby stosowania żadnego konkretnego wzoru. Dobrą praktyczną zasadą jest użycie wzorca, gdy fragmenty kodu są zwykle zastępowane lub wymagają częstych zmian, i należy być przygotowanym na przyjęcie zastrzeżenia złożonego kodu podczas korzystania z wzorca.
Pamiętaj, że Twoim celem powinna być prostota i stosować wzorzec, jeśli widzisz praktyczną potrzebę wprowadzenia zmian w kodzie.
Zasady ponad wzorami
Używanie wzorców może wydawać się sporne, jeśli mogą one ewidentnie prowadzić do zbyt zaawansowanych i skomplikowanych rozwiązań. Jednak zamiast tego znacznie bardziej interesujące dla programisty jest zapoznanie się z technikami i zasadami projektowania, które stanowią podstawę większości wzorców. W rzeczywistości jedna z moich ulubionych książek o „wzorcach projektowych” podkreśla to , powtarzając, jakie zasady mają zastosowanie do danego wzoru. Są na tyle proste, że pod względem trafności mogą być przydatne niż wzorce. Niektóre zasady są na tyle ogólne, że obejmują coś więcej niż programowanie obiektowe (OOP), takie jak Zasada Zastępowania Liskova , o ile można budować moduły swojego kodu.
Istnieje wiele zasad projektowania, ale te opisane w pierwszym rozdziale książki GoF są całkiem przydatne na początku.
Pozwól tym na chwilę zagłębić się w ciebie Należy zauważyć, że gdy napisano GoF, interfejs oznacza wszystko, co jest abstrakcją (co oznacza również superklasy ), czego nie należy mylić z interfejsem jako typem w Javie lub C #. Druga zasada pochodzi z obserwowanego nadużywania dziedziczenia, które niestety jest nadal powszechne .
Stamtąd możesz przeczytać o zasadach SOLID, które zostały ujawnione przez Roberta Cecila Martina (aka. Wujek Bob) . Scott Hanselman przeprowadził wywiad z wujkiem Bobem w podcastu na temat tych zasad :
Te zasady są dobrym początkiem do czytania i dyskusji z rówieśnikami. Może się okazać, że zasady przeplatają się ze sobą iz innymi procesami, takimi jak oddzielenie obaw i wstrzyknięcie zależności . Po pewnym czasie wykonywania TDD może się również okazać, że zasady te przychodzą naturalnie w praktyce, ponieważ trzeba do pewnego stopnia ich przestrzegać, aby stworzyć izolowane i powtarzalne testy jednostkowe.
źródło
Tym, o co najbardziej martwili się sami autorzy Design Patterns, był wzorzec „Visitor”.
To „zło konieczne” - ale często jest nadużywane, a potrzeba jego użycia często ujawnia bardziej fundamentalną wadę w Twoim projekcie.
Alternatywną nazwą dla wzorca „Odwiedzający” jest „Wiele wysyłek”, ponieważ wzorzec gościa jest tym, co otrzymujesz, gdy chcesz użyć jednego typu języka OO wysyłki do wybrania kodu do użycia na podstawie typu dwóch (lub więcej) różnych obiektów.
Klasycznym przykładem jest przecięcie między dwoma kształtami, ale jest jeszcze prostszy przypadek, który jest często pomijany: porównanie równości dwóch heterogenicznych obiektów.
W każdym razie często kończy się coś takiego:
Problem polega na tym, że połączyłeś wszystkie swoje implementacje "IShape". Zasugerowałeś, że za każdym razem, gdy chcesz dodać nowy kształt do hierarchii, będziesz musiał zmienić również wszystkie inne implementacje „kształtu”.
Czasami jest to poprawny minimalny projekt - ale przemyśl to. Czy Twój projekt naprawdę wymaga wysyłki na dwa typy? Czy chcesz napisać każdą kombinatoryczną eksplozję multimetod?
Często, wprowadzając inną koncepcję, możesz zmniejszyć liczbę kombinacji, które będziesz musiał napisać:
Oczywiście to zależy - czasami naprawdę musisz napisać kod, aby poradzić sobie z tymi wszystkimi różnymi przypadkami - ale warto zrobić sobie przerwę i pomyśleć przed podjęciem decyzji i użyciem Visitora. To może zaoszczędzić ci później dużo bólu.
źródło
Singletony - klasa używająca singletona X ma zależność od niej, która jest trudna do zauważenia i trudna do wyodrębnienia na potrzeby testowania.
Są używane bardzo często, ponieważ są wygodne i łatwe do zrozumienia, ale mogą naprawdę skomplikować testowanie.
Zobacz: Singletony są patologicznymi kłamcami .
źródło
Uważam, że wzorzec Metody Szablonowej jest ogólnie bardzo niebezpiecznym wzorcem.
źródło
Nie sądzę, abyś unikał wzorców projektowych (DP) i nie uważam, że powinieneś zmuszać się do korzystania z DP podczas planowania architektury. Powinniśmy używać PR tylko wtedy, gdy wynikają one w sposób naturalny z naszego planowania.
Jeśli od początku określimy, że chcemy korzystać z danego DP, na wiele naszych przyszłych decyzji projektowych będzie miał wpływ ten wybór, bez gwarancji, że wybrany przez nas DP jest dostosowany do naszych potrzeb.
Nie powinniśmy też traktować DP jako niezmiennej istoty, powinniśmy dostosować wzorzec do naszych potrzeb.
Podsumowując, uważam, że nie powinniśmy unikać DP, powinniśmy je przyjąć, gdy już nabierają kształtu w naszej architekturze.
źródło
Myślę, że moduł Active Record to nadużywany wzorzec, który zachęca do mieszania logiki biznesowej z kodem trwałości. Nie radzi sobie zbyt dobrze z ukrywaniem implementacji pamięci masowej w warstwie modelu i wiąże modele z bazą danych. Istnieje wiele alternatyw (opisanych w PoEAA), takich jak Table Data Gateway, Row Data Gateway i Data Mapper, które często zapewniają lepsze rozwiązanie iz pewnością pomagają zapewnić lepszą abstrakcję do przechowywania. Ponadto model nie powinien być przechowywany w bazie danych; co z przechowywaniem ich w formacie XML lub uzyskiwaniem do nich dostępu za pomocą usług internetowych? Jak łatwo byłaby zmienić mechanizm przechowywania Twoich modeli?
To powiedziawszy, moduł Active Record nie zawsze jest zły i jest idealny do prostszych aplikacji, w których inne opcje byłyby przesadą.
źródło
To proste ... unikaj wzorców projektowych, które nie są dla Ciebie jasne lub takie, w których nie czujesz się komfortowo .
Aby wymienić niektóre ...
istnieją pewne niepraktyczne wzorce , jak np .:
Interpreter
Flyweight
są też trudniejsze do uchwycenia , jak np .:
Abstract Factory
- Pełny abstrakcyjny wzór fabryczny z rodzinami utworzonych obiektów nie jest taki prosty, jak się wydajeBridge
- Może stać się zbyt abstrakcyjny, jeśli abstrakcja i implementacja są podzielone na poddrzewa, ale w niektórych przypadkach jest to bardzo użyteczny wzorzecVisitor
- Zrozumienie mechanizmu podwójnej wysyłki jest naprawdę MUSIi jest kilka wzorców, które wyglądają strasznie prosto , ale nie są tak jednoznaczne z różnych powodów związanych z ich zasadą lub realizacją:
Singleton
- niezbyt zły wzór, po prostu ZBYT nadużywany (często tam, gdzie nie jest odpowiedni)Observer
- świetny wzorzec ... po prostu sprawia, że kod jest znacznie trudniejszy do odczytania i debugowaniaPrototype
- kompilator transakcji sprawdza dynamikę (która może być dobra lub zła ... zależy)Chain of responsibility
- zbyt często po prostu wymuszone / sztucznie wciskane w projektDla tych „niepraktycznych” warto się dobrze zastanowić przed ich użyciem, bo zazwyczaj jest gdzieś bardziej eleganckie rozwiązanie.
Dla tych „trudniejszych do uchwycenia”… są naprawdę bardzo pomocne, gdy są używane w odpowiednich miejscach i dobrze wdrożone… ale koszmarne, gdy są niewłaściwie używane.
A teraz co dalej ...
źródło
Mam nadzieję, że nie będę za to zbytnio bić. Christer Ericsson napisał dwa artykuły ( jeden , dwa ) na temat wzorców projektowych w swoim blogu dotyczącym wykrywania kolizji w czasie rzeczywistym . Jego ton jest raczej szorstki i może trochę prowokacyjny, ale mężczyzna zna się na rzeczy, więc nie odrzuciłbym tego jako bredzeń wariata.
źródło
Niektórzy mówią, że lokalizator usług to anty-wzorzec.
źródło
Uważam, że wzorzec obserwatora ma wiele do odpowiedzenia, działa w bardzo ogólnych przypadkach, ale gdy systemy stają się bardziej złożone, staje się koszmarem, wymagającym powiadomień OnBefore (), OnAfter () i często wysyłania asynchronicznych zadań, aby uniknąć ponownego zachwyt. Znacznie lepszym rozwiązaniem jest opracowanie systemu automatycznej analizy zależności, który instrumentuje dostęp do wszystkich obiektów (z barierami odczytu) podczas obliczeń i automatycznie tworzy krawędź na wykresie zależności.
źródło
Uzupełnienie postu Spoike'a, Refaktoryzacja do wzorców to dobra lektura.
źródło
Iterator to jeszcze jeden wzorzec GoF, którego należy unikać lub przynajmniej używać go tylko wtedy, gdy żadna alternatywa nie jest dostępna.
Alternatywy to:
pętla for-each. Ta konstrukcja jest obecna w większości języków głównego nurtu i może być używana w celu uniknięcia iteratorów w większości przypadków.
selektory à la LINQ lub jQuery. Należy ich używać, gdy for-each nie jest odpowiednie, ponieważ nie wszystkie obiekty z kontenera powinny być przetwarzane. W przeciwieństwie do iteratorów, selektory pozwalają w jednym miejscu wskazać, jakie obiekty mają być przetwarzane.
źródło
yield
iteratorowi. Eric White prowadzi świetną dyskusję na ten temat w C # 3.0: blogs.msdn.com/b/ericwhite/archive/2006/10/04/… . Zapoznaj się również z dyskusją Jeremy'ego Liknessa na temat programów z iteratorami: wintellect.com/CS/blogs/jlikness/archive/2010/03/23/… .