Wzorce projektowe, których należy unikać [zamknięte]

Wiele osób zdaje się zgadzać, że wzór Singletona ma wiele wad, a niektórzy sugerują nawet całkowite unikanie wzoru. Jest doskonała dyskusja tutaj . Wszelkie uwagi dotyczące wzoru Singletona proszę kierować na to pytanie.

Moje pytanie : Czy istnieją inne wzorce projektowe, których należy unikać lub stosować z wielką starannością?

Author: Community, 2009-01-16

12 answers

Wzory są złożone

Wszystkie wzorce projektowe powinny być używane ostrożnie. Moim zdaniem powinieneś refaktorować w stronę wzorców , gdy jest ku temu ważny powód, zamiast od razu implementować wzorce. Ogólny problem z używaniem wzorców polega na tym, że dodają one złożoności. Nadużywanie wzorców sprawia, że dana aplikacja lub system jest kłopotliwy do dalszego rozwoju i utrzymania.

Przez większość czasu istnieje proste rozwiązanie i nie musisz stosować żadnych konkretnych wzór. Dobrą zasadą jest używanie wzorca, gdy fragmenty kodu mają tendencję do wymiany lub muszą być często zmieniane i być przygotowane do przyjęcia zastrzeżenia złożonego kodu podczas używania wzorca.

Pamiętaj, że twoim celem powinna być prostota i użyj wzorca, jeśli widzisz praktyczną potrzebę wspierania zmian w kodzie.

Zasady nad wzorcami

Użycie wzorców może wydawać się sporne, jeśli ewidentnie mogą prowadzić do nadmiernej inżynierii i złożoności rozwiązania. Jednak dla programisty o wiele bardziej interesujące jest zapoznanie się z technikami i zasadami projektowania , które stanowią fundament dla 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 wzorca. Są one na tyle proste, że mogą być użyteczne niż wzorce pod względem znaczenia. Niektóre z zasad są na tyle ogólne, że obejmują więcej niż zorientowane obiektowo programowanie (OOP), takie jak Liskov Substitution Principle , o ile możesz budować Moduły swojego kodu. Istnieje wiele zasad projektowania, ale te opisane w pierwszym rozdziale książki GoF są bardzo przydatne na początek.
  • Program do 'interfejsu', a nie'implementacji'. (Gang of Four 1995:18)
  • faworyzować 'skład obiektu' nad 'dziedziczeniem klas'. (Gang of Four 1995:20)

Niech na chwilę ci się to przytrafiło. Należy zauważyć, że gdy GoF został napisany, interfejs oznacza wszystko, co jest abstrakcją (co również oznacza super klasy), nie należy mylić z interfejsem jako typem w Javie lub C#. Druga zasada pochodzi z zaobserwowanego nadużywania dziedziczenia, które jest niestety nadal powszechne dzisiaj .

Stamtąd można przeczytać naSOLID principles , który został ogłoszony przez Roberta Cecila Martina (aka. Wujek Bob) . Scott Hanselman przeprowadził wywiad z wujkiem Bobem w podcaście na temat tych zasad :

  • S zasada odpowiedzialności ingle
  • o zasada zamknięcia pióra
  • L zasada substytucji iskow
  • i zasada segregacji nterface
  • D zasada inwersji ependencji

Te zasady są dobrym początkiem do przeczytania i omówienia z rówieśnikami. Może się okazać, że zasady przeplatają się ze sobą i z innymi procesami, takimi jak separacja obaw I iniekcja zależności . Po wykonaniu TDD przez jakiś czas możesz również zauważyć, że zasady te pojawiają się naturalnie w praktyce, ponieważ musisz je do pewnego stopnia przestrzegać, aby stworzyć izolowane i powtarzalne testy jednostkowe.

 141
Author: Spoike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:19

Tym, o co najbardziej martwili się sami autorzy wzorców projektowych, był wzór "Gościa".

Jest to "zło konieczne" - ale jest często nadużywane, a jego potrzeba często ujawnia bardziej fundamentalną wadę w Twoim projekcie.

Alternatywną nazwą dla wzorca "Visitor" jest "Multi-dispatch", ponieważ wzorzec odwiedzający jest tym, co kończy się, gdy chcesz użyć języka oo wysyłki jednego typu, aby wybrać kod do użycia na podstawie typu dwóch (lub więcej) różnych obiektów.

Klasycznym przykładem jest to, że masz przecięcie między dwoma kształtami, ale jest jeszcze prostszy przypadek, który jest często pomijany: porównywanie równości dwóch heterogenicznych obiektów.

W każdym razie, często kończy się z czymś takim:

interface IShape
{
    double intersectWith(Triangle t);
    double intersectWith(Rectangle r);
    double intersectWith(Circle c);
}
Problem w tym, że połączyłeś ze sobą wszystkie swoje implementacje "IShape". Zasugerowałeś, że za każdym razem, gdy chcesz dodać nowy kształt do hierarchii, musisz zmienić wszystkie inne Implementacje" Shape " też.

Czasami jest to poprawny projekt minimalny - ale przemyśl to. Czy twój projekt naprawdę nakazuje, że musisz wysłać na dwa typy? Czy jesteś gotów napisać każdą kombinatoryczną eksplozję wielu metod?

Często, wprowadzając inną koncepcję, możesz zmniejszyć liczbę kombinacji, które będziesz musiał napisać:

interface IShape
{
    Area getArea();
}

class Area
{
    public double intersectWith(Area otherArea);
    ...
}

Oczywiście to zależy-czasami naprawdę trzeba napisać kod do Obsługa wszystkich tych różnych przypadków-ale warto zrobić przerwę i pomyśleć przed podjęciem decyzji i użyciem Visitor. To może zaoszczędzić Ci wiele bólu później.

 21
Author: Paul Hollingsworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-16 10:37:42

Singletons-Klasa używająca Singletona X ma od niej zależność, która jest trudna do zauważenia i trudna do wyizolowania dla testów.

Są używane bardzo często, ponieważ są wygodne i łatwe do zrozumienia, ale mogą naprawdę skomplikować testy.

Zobacz Singletony są patologicznymi kłamcami.

 16
Author: orip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-16 08:16:11

Uważam, że wzór metody szablonowej jest ogólnie bardzo niebezpieczny.

  • wiele razy wykorzystuje swoją hierarchię dziedziczenia z "złych powodów".
  • klasy bazowe mają tendencję do zaśmiecania się wszelkimi rodzajami niezerelowanego kodu.
  • Zmusza do zablokowania projektu, często dość wcześnie w procesie rozwoju. (Przedwczesne zablokowanie w wielu przypadkach) Zmiana tego na późniejszym etapie staje się coraz trudniejsza.
 14
Author: krosenvold,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-16 07:19:44

Myślę, że nie powinieneś unikać wzorców projektowych (DP), i nie sądzę, że powinieneś zmuszać się do używania DPs przy planowaniu swojej architektury. Powinniśmy używać DPs tylko wtedy, gdy są one naturalne z naszego planowania.

Jeśli Od początku zdefiniujemy, że chcemy użyć danego DP, to na wiele naszych przyszłych decyzji projektowych będzie wpływał ten wybór, bez żadnej gwarancji, że DP, którą wybraliśmy, jest dostosowany do naszych potrzeb.

Jedną rzeczą, której nie powinniśmy robić, to traktować DP jako niezmienną / align = "left" /

Podsumowując, myślę, że nie powinniśmy unikać DPs, powinniśmy je objąć, gdy już nabierają kształtu w naszej architekturze.

 9
Author: Megacan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-16 09:52:56

Myślę, że Active Record jest nadużywanym wzorcem, który zachęca do mieszania logiki biznesowej z kodem persistance. Nie sprawdza się zbyt dobrze ukrywanie implementacji pamięci masowej z warstwy modelu i powiązanie modeli 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 i z pewnością pomagają zapewnić lepszą abstrakcję do przechowywania. Również Twój model nie powinien muszą być przechowywane w bazie danych; a co z przechowywaniem ich jako XML lub uzyskiwaniem do nich dostępu za pomocą usług internetowych? Jak łatwo byłoby zmienić mechanizm przechowywania swoich Modeli?

To powiedziawszy, Active Record nie zawsze jest zły i jest idealny do prostszych aplikacji, w których inne opcje byłyby przesadą.

 7
Author: Tim Wardle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-16 07:20:15

To proste ... unikaj wzorców projektowych, które są niejasne dla Ciebie lub tych, w których nie czujesz się komfortowo .

Aby wymienić niektóre ...

Istnieją pewne niepraktyczne wzory , jak np.:

  • Interpreter
  • Flyweight

Są też pewne trudniejsze do uchwycenia , np.:

  • Abstract Factory - pełny abstrakcyjny wzór fabryczny z rodzinami tworzonych obiektów to nie taka bryza jak się wydaje [25]}
  • Bridge - może być zbyt abstrakcyjny, jeśli abstrakcja i implementacja są podzielone na podtypy, ale jest bardzo użyteczny wzorzec w niektórych przypadkach
  • Visitor - Mechanizm podwójnej wysyłki jest naprawdę koniecznością.]}

I są pewne wzory, które wyglądają strasznie prosto , ale nie są tak jasnym wyborem z różnych powodów związanych z ich zasadą lub realizacja:

  • Singleton - nie do końca zły wzór, po prostu zbyt nadużywany (często tam, gdzie nie jest odpowiedni)
  • Observer - świetny wzór ... po prostu sprawia, że kod jest znacznie trudniejszy do odczytania i debugowania]}
  • Prototype - 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 wepchnięte w projekt

Dla tych "niepraktycznych", jeden naprawdę warto o tym pomyśleć przed ich użyciem, ponieważ zwykle gdzieś jest bardziej eleganckie rozwiązanie.

Dla tych "trudniejszych do uchwycenia"... są naprawdę bardzo pomocne, gdy są używane w odpowiednich miejscach i gdy są dobrze realizowane ... ale są koszmarem, gdy są niewłaściwie używane. Co dalej ?..
 7
Author: Thetam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-21 13:38:17

Mam nadzieję, że nie dam się za bardzo za to pobić. Christer Ericsson napisał dwa artykuły (Jeden, Dwa) na temat wzorców projektowych w swoim blogu wykrywanie kolizji w czasie rzeczywistym . Jego ton jest dość surowy i może trochę prowokacyjny, ale facet zna się na rzeczy, więc nie lekceważę tego jako rabusiów szaleńca.

 5
Author: falstro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-16 09:06:01

Niektórzy mówią, że service locator jest wzorzec anty.

 5
Author: Arnis Lapsa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-13 12:42:28

Uważam, że wzorzec obserwatora ma wiele do odpowiedzi, działa w bardzo ogólnych przypadkach, ale gdy systemy stają się bardziej złożone, staje się koszmarem, wymagając powiadomień OnBefore (), OnAfter() i często delegowania zadań asynchronicznych, aby uniknąć ponownego włączenia. Znacznie lepszym rozwiązaniem jest opracowanie systemu automatycznej analizy zależności, który instrumentuje dostęp wszystkich obiektów (z barierami odczytu) podczas obliczeń i automatycznie tworzy krawędź na wykresie zależności.

 2
Author: Jesse Pepper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-16 07:11:07
 2
Author: Adeel Ansari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-16 07:34:58

Iterator jest jeszcze jednym wzorcem GoF, którego należy unikać, a przynajmniej używać go tylko wtedy, gdy żadna alternatywa nie jest dostępna.

Alternatywy to:

  1. Dla-każdej pętli. Ta konstrukcja jest obecna w większości głównych języków i może być używana w celu uniknięcia iteratorów w większości przypadków.

  2. Selektory a la LINQ lub jQuery. Powinny być używane, gdy for-each nie jest odpowiednie, ponieważ nie wszystkie obiekty z kontenera powinny być przetwarzane. W przeciwieństwie do iteratorów, selektory pozwala zamanifestować w jednym miejscu, jakiego rodzaju obiekty mają być przetwarzane.

 0
Author: Volodymyr Frolov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-01 21:50:29