Czy pisząc kod zorientowany obiektowo, powinienem zawsze kierować się wzorcem projektowym?

37

Czy istnieje jakiś wzorzec projektowy dla dowolnego programu obiektowego? Pytam o to, ponieważ ostatnio widziałem implementację Doorklasy z Lock. Było to częścią testu, a odpowiedź brzmiała, że ​​kod jest zgodny ze wzorcem Null Object:

class Lock
{
public:
    virtual void close() = 0;
    virtual void open() = 0;
    virtual bool is_open() const = 0;
    virtual ~Lock() { }
};

class DummyLock
    : public Lock
{
private:
    DummyLock();
    DummyLock(const DummyLock&) = delete;
    DummyLock& operator=(const DummyLock&) = delete;

private:
    void close() { }
    void open() { }
    bool is_open() const { return true; }

public:
    static DummyLock m_instance;
};

class Door
{
public:
    Door() : m_lock(DummyLock::m_instance) { }
    Door(Lock &lock) : m_lock(lock) { }

public:
    Lock& get_lock() const { return m_lock; }

private:
    Lock &m_lock;
};

To sprawiło, że pomyślałem: ten kod ma dobry wzorzec projektowy, mimo że opis jest tak prosty (ta klasa projektuje klasę drzwi z zamkiem), więc jeśli piszę bardziej złożony kod, czy zawsze powinien istnieć jakiś wzorzec projektowy, który ja śledzę?

użytkownik2030677
źródło
51
Czy myślisz, że mógłbyś mówić całkowicie w idiomach? Nie? Zatem nie powinieneś budować swoich programów, łącząc ze sobą wzorce projektowe.
Kilian Foth,
4
W twoim przykładzie wzorzec obiektu zerowego jest dodawany tylko do celów akademickich, nie wprowadza „dobrego projektu” do tego kodu.
Doc Brown
4
@djechlin: innymi słowy, użyj wzoru „dwa słowa” :)
Michael Shaw
11
Problem polega na tym, że zbyt wiele osób uważa, że ​​wzorce projektowe są substytutem myśli i substytutem doświadczenia (co implikuje pewną ilość prób i błędów). Nie można wziąć książki pełnej wzorców projektowych i złożyć je razem, tak jak Tinker Toys, aby stworzyć aplikację o niebanalnym rozmiarze, złożoności i przyzwoitej jakości. Nawet doświadczeni programiści często muszą wypróbować dwa lub trzy projekty, zanim znajdą taki, który działa.
Daniel R Hicks,

Odpowiedzi:

143

czy zawsze powinien być jakiś wzór, który podążam?

Dobry Boże NIE!

To znaczy, można śmiało powiedzieć, że każdy kod losowy obserwuje jakiś losowy wzór XYZ, ale to nie jest bardziej przydatna niż mnie twierdząc, że jest królem mojego komputera krzesła. Nikt tak naprawdę nie wie, co to znaczy, a nawet ci, którzy to robią, nie uszanują mojego twierdzenia.

Wzorce projektowe są narzędziem komunikacji, dzięki czemu programiści mogą powiedzieć innym programistom, co zostało zrobione lub co należy zrobić, bez poświęcania czasu na powtarzanie się. A ponieważ są to rzeczy, które pojawiają się wiele razy, są one przydatnymi pojęciami dla programistów, aby nauczyć się „hej, dzięki czemu XYZ zawsze wydaje się pojawiać, ponieważ jest dobry / użyteczny”.

Oni nie zastępuje potrzeby, aby myśleć za siebie, aby dostosować wzory dla wyjątkowej problemu przed sobą, lub do obsługi wszystkich nieuniknionych rzeczy, które nie pasują do przyjemnych wiadrach.

Telastyn
źródło
5
Twój pierwszy akapit jest częścią odpowiedzi na to pytanie. Coś staje się wzorem, kiedy się powtarza. Jeśli powtórzy się wystarczająco dużo razy, aby wymagać komunikacji, jest to wzorzec i korzysta z nazwy. Niektórzy twierdzą nawet, że wzór rozwija się tylko dlatego, że brakuje pewnej abstrakcji. Pogoń za wzorami to droga do zniesławienia jako członek osławionego kultu Cargo.
Mag
11
@Cerad: Jasne, o ile obiecujesz, że nie napiszesz również lekcji Boga!
yatima2975,
9
John Doe - inżynier techniczny, Generic Code Monkey i King of the computer chair
hjk
1
Prawdopodobnie projekt powinien wykorzystywać wzorce tam, gdzie jest to właściwe, a klasy powinny być nazywane jako takie. Są ważnym narzędziem. Banie się the_cult(tm) jest równie niebezpieczne.
Gusdor
25
Świetna odpowiedź! Moją jedyną krytyką jest to, że „Drogi Boże NIE!” nie jest wystarczająco duży.
tobyink
37

Nie.

Oto, co powiedział o tym Gang of Four (który pierwotnie spopularyzował wzory projektowe) w swojej książce :

„Żadna dyskusja na temat używania wzorców projektowych nie byłaby kompletna bez kilku słów o tym, jak ich nie używać. Wzorców projektowych nie należy stosować bez rozróżnienia. Często osiągają elastyczność i zmienność poprzez wprowadzenie dodatkowych poziomów pośrednich, co może skomplikować projekt i / lub kosztować trochę wydajności. Wzorzec projektowy powinien być stosowany tylko wtedy, gdy elastyczność, którą zapewnia, jest rzeczywiście potrzebna. ”

Przykład, który pokazujesz, w rzeczywistości niewiele zdziała (nie sądzę, żeby miał tak być, myślę, że miał być tylko przykładem). Sam w sobie nie potrzebuje wzorca zerowego obiektu. W kontekście większego programu może tak być.

Niewłaściwe podejście zakłada, że ​​tylko dlatego, że zostało oznaczone jako „wzorzec projektowy”, musi być dobre, a następnie szuka więcej miejsc, w których można wcisnąć więcej wzorców. Użyj ich, gdy pasują do programu i faktycznie rozwiązują problem.

Michael Shaw
źródło
7
Książka jest Design Patterns: Elements of Reusable Object-Oriented Software autorstwa Ericha Gammy, Richarda Helma, Ralpha Johnsona i Johna Vlissidesa.
developerwjk
4
+1 Za faktyczne cytowanie źródła wzorców projektowych.
Pharap
29

jeśli piszę bardziej złożony kod, czy zawsze powinien być jakiś wzorzec projektowy, który przestrzegam?

Nie. Wzory projektowe to po prostu: wzory w relacjach między obiektami. Innymi słowy, relacje, które są używane i ponownie wykorzystywane tak często, że ktoś powiedział: „Hej, wydaje się, że dużo to robimy, nazwijmy to”. Lista wzorców projektowych nie została ustalona od razu na początku OOP, a następnie przekazana przez GOF ! Zostały odkryte i ostatecznie udokumentowane, a następnie spopularyzowane przez książkę.

To powiedziawszy, dużą zaletą wzorców projektowych jest to, że ułatwiają myślenie o projektowaniu oprogramowania na wyższym poziomie. Pozwalają pominąć martwienie się o szczegóły implementacji i zastanowić się więcej na temat ogólnego obrazu. W tym sensie uwalniają cię od drobiazgów, ale mogą cię również ograniczać w taki sam sposób, w jaki sposób, w jaki wyrażasz siebie, może być ograniczany przez słowa, które znasz. Więc może nadszedł czas, kiedy nie jest wzorzec projektowania dla większości z tego, co robisz po prostu dlatego, że wzory, które znasz są warunki, w których myślisz. Miej oczy otwarte na przypadki, w których możesz nadużywać wzoru i gdzie może być konieczne głębsze zastanowienie się nad lepszymi sposobami robienia rzeczy.

Należy również pamiętać, że w praktyce często nie implementuje się danego wzorca projektowego, a rozpoznaje się go w istniejącym kodzie, takim jak struktura obiektowa. Znajomość typowych wzorców projektowych znacznie ułatwia nauczenie się, w jaki sposób ma być używany framework, ponieważ można zobaczyć relacje między klasami w terminach, które już rozumiesz.

Caleb
źródło
10

Wzory projektowe mają dwie zalety

  1. Są łatwe do opisania innym programistom, ponieważ ludzie zazwyczaj zgadzają się co do tego, jakie są wzorce
  2. Byli bici przez naszych poprzedników dość starannie, więc ich mocne i słabe strony są dobrze zrozumiane.

Cele każdego programu powinny być

  1. To działa. Musi robić wszystko, co jest celem końcowym, lub nie ma znaczenia, ile wzorców projektowych zastosujesz. Wzorce projektowe OO ułatwiają podzielenie problemu na łatwe do zrozumienia bity, dzięki czemu łatwiej jest udowodnić, że działa.
  2. Jest łatwy do odczytania. To tutaj wzorce projektowe są ładne. Problemy OO, które rozwiązują, są skomplikowane. Jeśli rozwiążesz je w „standardowy” sposób, będzie to łatwiejsze dla następnego programisty
  3. Łatwo rośnie. Prawie 0 nowoczesnych programów kończy się tam, gdzie wszyscy je zaplanowali. Każdy program rośnie po jego początkowej wersji. Wzory OO są znane z tego, że są wyjątkowo dobre w uprawie.

Biorąc to wszystko pod uwagę, zauważ, że każde odniesienie do wzorców projektowych OO brzmi „są po prostu dobre w pracy”. Nie są idealne, ale bardzo skutecznie wypełniają niszę. Używaj ich, gdy działają, unikaj ich, gdy nie działają.

Jako przykład „złożonego kodu”, jak wspomniałeś w swoim pytaniu, weź język skryptowy, który napisałem. Większość z nich to OO z wzorami projektowymi wszędzie. Jednak, jeśli chodzi o pisanie śmietnika, bezceremonialnie porzuciłem wszystkie pretensje OO, ponieważ konkretne rzeczy, które musiałem zrobić, były lepiej wymodelowane jako dobre staromodne bitowanie. W całości nie ma wzorca OO, dopóki nie doszło do pisania finalizatorów, w których OO znów zaczęło być użytecznym modelem. Bez żadnej pompki ani okoliczności kod nagle zmienił się z powrotem w stosowanie technik OO.

Używaj wzorców projektowych, ilekroć ulepszają Twój produkt; unikaj ich, gdy pogorszą twój produkt.

Cort Ammon
źródło
2
Myślę, że ostatnie zdanie powinno być na górze pogrubioną czcionką lub jako podsumowanie.
Pharap
5

Zrobię trochę trend, ponieważ odpowiedź jest bardziej subtelna niż na to pozwalają inne odpowiedzi. Każda klasa, którą piszesz, nie powinna stosować wzorca projektowego, ale większość nietrywialnych programów, które piszesz, prawdopodobnie powinna.

Nietrywialny program bez wzorców projektowych wskazuje:

  • Twój program jest tak wyjątkowy, że żadna jego część nie jest podobna do typowych problemów, z którymi mieli do czynienia wcześniej programiści. Lub
  • Twój program zawiera te typowe problemy, ale rozwiązałeś je w lepszy sposób, o którym nikt wcześniej nie pomyślał.

Oba scenariusze są bardzo mało prawdopodobne, bez obrazy.

To nie znaczy, że wzór powinien kierować twoim projektem, lub że powinieneś wstawić jeden bez rozróżnienia, ponieważ uważasz, że będzie źle wyglądać, jeśli nie. Niepoprawny wzorzec projektowy jest gorszy niż żaden.

Oznacza to, że powinieneś spojrzeć na brak wzorców projektowych w całym programie jako zapach kodu. Coś, co sprawia, że ​​musisz spojrzeć drugi raz i ponownie ocenić, czy twój projekt nie może być czystszy. Jeśli w tym momencie zdecydujesz się pozostawić wzorce projektowe poza programem, powinna to być świadoma, świadoma decyzja, a nie przypadek.

Na przykład nie mówisz: „Muszę zamodelować drzwi i zamek, jakiego wzoru powinienem użyć?” Jeśli jednak zaprojektowałeś go najpierw bez użycia wzorców projektowych, powinno to skłonić cię do powiedzenia czegoś takiego: „Mam w tym kodzie strasznie dużo zerowych kontroli, zastanawiam się, czy istnieje wzorzec projektowy, który mógłby pomóc w zarządzaniu nimi”.

Zobacz różnicę? To subtelne, ale ważne rozróżnienie.

Karl Bielefeldt
źródło
5
Istnieje wiele częstszych problemów (i ich wspólnych rozwiązań) niż wzorców projektowych. Wzorce projektowe to skatalogowany podzbiór typowych rozwiązań OO - nie zbiór wszystkich popularnych rozwiązań.
Michael Shaw
1
Czy mógłbyś zdefiniować, co rozumiesz przez „nietrywialny”, miałem wrażenie, że termin „nietrywialny” był subiektywny.
Pharap
1
To jest subiektywne. Mam na myśli rodzaj programu, który napiszesz w zespole w pracy, wymagając na bieżąco wielu opiekunów.
Karl Bielefeldt
Jeśli masz szczęście, aby później zobaczyć swój problem. Jasne kontrole zerowe. Luki w zabezpieczeniach? Inne podstępne sposoby, w jakie program złamie się podczas konserwacji? Problemy, które odkryje tylko następny inżynier? O wiele więcej szczęścia.
djechlin
„Muszę wymodelować drzwi i zamek, jaki powinien być interfejs? Czy wydajność będzie częścią umowy? Czy powinienem skorzystać z usługi lub biblioteki? W jaki sposób zostaną przekazane zasoby?” należy zadać wszystko i powinieneś mieć odpowiedzi, które są zasadniczo uważane za wzorce projektowe.
djechlin
4

Złamane pytanie. Pozwól, że dam ci nową definicję wzoru projektowego, który cofnąłby wiele szkód wyzwolonych przez GoF: wzór projektowy jest dobrą praktyką kodowania . to jest to!

Każdy dość skomplikowany moduł będzie miał kilka wzorów projektowych. Za każdym razem, gdy buforujesz, jest to prawdopodobnie wzorzec wagi lekkiej, ale nie cofnę twojego stopnia programistycznego, jeśli tak go nie nazwiesz. Za każdym razem, gdy masz w sobie funkcję oddzwaniania, jesteś w pewnym rodzaju zdarzenia / pożaru / oddzwaniania. itp. Jeśli masz słowo „statyczny”, masz singletona. Jeśli masz konstruktora statycznego, masz wzorzec fabryczny. Jeśli zasób zostanie przekazany do modułu, używasz wstrzykiwania zależności.

„Wzorzec projektowy” to złamany termin źle spopularyzowany przez GoF, który sprawia, że ​​brzmi, jakby wszystkie wzory były na tym samym poziomie, lub powinieneś użyć lekarza zalecanego od 3 do 5 na klasę. Za każdym razem, gdy robisz coś dobrze, co zrobił ktoś inny, jest to wzorzec projektowy . A for(;;)jest na przykład częstym wzorem reprezentującym nieskończoną pętlę.

Nie powinieneś próbować nauczyć się wielu wzorców projektowych. Wiedza programistyczna nie jest indeksowana według wzorców projektowych! Zamiast tego powinieneś nauczyć się pisać dobry kod , czytając książki, blogi i uczestnicząc w konferencjach w swojej dziedzinie. Na przykład, jeśli jesteś już przy użyciu iniekcji zależność, ale po prostu nie zostały oznakowane go, można korzystać z zawsze używając DI lub za pomocą ramy MKOl. Lub jeśli masz problemy z kodowaniem bezpośrednio w zdarzeniach i wywołaniach zwrotnych, zapoznaj się z Haskell, aby zapoznać się z funkcjonalnymi wzorami projektowymi i stanie się to łatwe.

A jeśli cała twoja klasa brzmi jak jedna wielka rzecz, którą ktoś zrobił dobrze, dlaczego wymyślasz koło? Po prostu użyj ich rzeczy.

djechlin
źródło
2
W jakim języku jest for(;;)idiomatyczny? To chyba nie jest najlepszy przykład czegoś, co ktoś zrobił „dobrze”.
Telastyn
1
@Telastyn C, C ++, Java, JavaScript, C #.
djechlin
2
Nigdy nie widziałem, żeby ktokolwiek wolał while(true)(a while(1)) to w C, C ++, Java lub C # przez ponad 20 lat mojego programowania.
Telastyn
1
@Telastyn stackoverflow.com/a/2611744/1339987 fwiw Zacząłem preferować podczas (prawda), ponieważ wydaje mi się bardziej czytelny.
djechlin
1
Zawsze używam do (;;). Bez konkretnego powodu, prawdopodobnie gdzieś to przeczytałem. Podoba mi się fakt, że nie ma w tym żadnych zmiennych ani stałych. W każdym razie @Telastyn już kogoś poznałeś .
Ant
0

Zawsze należy przestrzegać zasad projektowania OO (np. Modułowość, ukrywanie informacji, wysoka spójność itp.). Wzory projektowe są stosunkowo wyrafinowaną niszą zasad projektowania OO, szczególnie jeśli weźmiesz pod uwagę zasadę KISS .

Wzory są rozwiązaniem typowych problemów projektowych. Problemy te pochodzą z jednego z dwóch miejsc (lub ich kombinacji): obszaru problemów (np. Oprogramowania do zarządzania zasobami ludzkimi w firmie) i obszaru rozwiązań . Programy OO to instancja w przestrzeni rozwiązań (np. Jeden z wielu sposobów zaprojektowania programu OO w celu ułatwienia zarządzania zasobami ludzkimi).

Nie jest tak łatwo wiedzieć, kiedy użyć wzoru. Niektóre wzorce są niskiego poziomu, bliższe kodowaniu i przestrzeni rozwiązań (np. Singleton, obiekt Null, Iterator). Inne są motywowane wymaganiami w obszarze problemów (np. Wzorzec poleceń do obsługi cofania / ponawiania, strategia do obsługi wielu typów plików wejściowych / wyjściowych).

Wiele wzorców wynika z potrzeby obsługi odmian oprogramowania w przyszłości. Jeśli nigdy nie będziesz musiał dokonywać tych zmian, wzór może być nadmiernie zaprojektowany. Przykładem może być użycie wzorca adaptera do pracy z istniejącą zewnętrzną bazą danych HR. Decydujesz się na użycie adaptera, ponieważ bieżąca baza danych działa z Oracle i możesz w przyszłości obsługiwać NoSQL. Jeśli NoSQL nigdy nie przyjdzie do twojej organizacji, ten kod adaptera może być bardzo bezużyteczny. Zobacz YAGNI . Obsługa odmian, które nigdy nie nadejdą, to niewłaściwe użycie wzorca projektowego.

Fuhrmanator
źródło
0

Wzory są powszechnymi rozwiązaniami typowych problemów. Zawsze podążamy za niektórymi wzorcami, wzorce GoF dotyczą najbardziej powtarzających się wzorów. Żeby mieć wspólne zrozumienie i wspólne podejście znane inżynierom oprogramowania.

To powiedziawszy, moja odpowiedź brzmi „nie”, ale tak, zawsze postępujesz według własnego wzoru. Jak słusznie to ujmuje GoF-

Wzór jednej osoby jest prymitywnym budulcem innej osoby.

Dobry cytat.

Syed Priom
źródło
wydaje się, że nie oferuje to nic istotnego w porównaniu z punktami przedstawionymi i wyjaśnionymi w poprzednich 7 odpowiedziach
gnat
W porządku. Zauważyłem, że podniosłem ogólną kwestię ... to dotyczy Wzorów projektowych jako dyskusja teoretyczna.
Syed Priom,
„Ta strona polega na uzyskiwaniu odpowiedzi . To nie jest forum dyskusyjne ...” ( tour )
gnat
Odpowiedziałem na pytanie. Dziękuję Ci. Ta rozmowa kończy się tutaj.
Syed Priom,
@gnat jest jednak o wiele bardziej zwięzły.
djechlin
0

Kiedy piszę kod, nie planuję celowo używać tylu wzorców projektowych, ile tylko mogę. Ale, jak sądzę, podświadomie, kiedy mam problem z kodowaniem, jeden ze wzorów wydaje się pasować i po prostu go używam. A czasem nic nie pasuje. Dla mnie ważniejsze jest pisanie kodu, który wykonuje pracę, jest łatwy w utrzymaniu i rozbudowie.

Oto artykuł na temat stosowania zasad OOD przy użyciu wzorców projektowych, a także przykłady kodu (w C ++). Pokazuje, jak i kiedy zastosować niektóre wzorce projektowe do napisania czystego kodu.

woda różana
źródło
2
Ten artykuł został napisany wczoraj; czy w ogóle jesteś związany z blogiem? Jeśli tak, proszę ujawnić to powiązanie .
Martijn Pieters