При написании объектно-ориентированного кода я должен всегда следовать шаблону проектирования?

37

Есть ли мыслимый шаблон проектирования для какой-либо объектно-ориентированной программы? Я спрашиваю об этом, потому что недавно я увидел реализацию Doorкласса с Lock. Это было частью теста, и в ответ было сказано, что код соответствует шаблону 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;
};

Это заставило меня задуматься: этот код следует хорошему шаблону проектирования, даже если описание очень простое (этот класс разрабатывает класс дверей с замком), поэтому, если я пишу более сложный код, всегда должен быть какой-то шаблон проектирования, который я я следую?

user2030677
источник
51
Как вы думаете, вы могли бы говорить полностью в идиомах? Нет? Тогда вам не следует создавать свои программы, объединяя шаблоны проектирования.
Килиан Фот
4
В вашем примере шаблон объекта Null добавляется только для академических целей, он не вводит «хороший дизайн» в этот код.
Док Браун
4
@djechlin: другими словами, используйте шаблон дизайна «два слова» :)
Майкл Шоу,
11
Проблема заключается в том, что слишком многие люди считают, что шаблоны проектирования являются заменой мысли и заменой опыта (что подразумевает определенное количество проб и ошибок). Вы не можете взять книгу, полную шаблонов дизайна, и собрать их вместе, как Tinker Toys, чтобы создать приложение с нетривиальным размером, сложностью и достойным качеством. Даже опытным программистам часто приходится пробовать два или три проекта, прежде чем они найдут тот, который работает.
Даниэль Р Хикс

Ответы:

143

всегда ли должен быть какой-то шаблон дизайна, которому я следую?

Дорогой Бог НЕТ!

Я имею в виду, вы можете пойти дальше и сказать, что любой случайный код следует некоторому случайному шаблону XYZ, но это не более полезно, чем я, претендующий на звание короля моего компьютерного стула. Никто на самом деле не знает, что это значит, и даже те, кто это делает, не будут точно уважать мои требования.

Шаблоны проектирования являются средством коммуникации, так что программисты могут рассказать другим программистам, что сделано или что нужно сделать, не тратя много времени на повторение. И поскольку эти вещи возникают несколько раз, они полезны для программистов, которые учат: «Эй, создание XYZ всегда кажется подходящим, потому что это хорошо / полезно».

Они не заменяют вам необходимости думать самостоятельно, подгонять шаблоны для уникальной проблемы перед вами или обрабатывать все неизбежные вещи, которые не укладываются в хорошие ведра.

Telastyn
источник
5
Ваш первый абзац является частью того, как я бы ответил на это. Что-то становится шаблоном, когда это повторяется. Если это повторяется достаточно много раз, чтобы требовать связи, это шаблон и выгода от имени. Некоторые даже утверждают, что шаблон развивается только потому, что отсутствует некоторая абстракция. Погоня за образцами - это путь к позору в качестве члена хваленого Грузового культа.
Маг
11
@Cerad: Конечно, до тех пор, пока вы обещаете не писать уроки Бога!
yatima2975
9
Джон Доу - Технический инженер, Обезьяна общего кода и Король его компьютерного стула
HJK
1
Возможно, дизайн должен использовать шаблоны там, где это необходимо, и классы должны быть названы как таковые. Они важный инструмент. Бояться the_cult(тм) так же опасно.
Гусдор
25
Отличный ответ! Моя единственная критика заключается в том, что «Дорогой Бог НЕТ!» недостаточно велик
Tobyink
37

Нет.

Вот что «Банда четырех» (которая изначально популяризировала шаблоны проектирования) должна была сказать об этом в своей книге :

«Ни одно обсуждение того, как использовать шаблоны проектирования, не будет полным без нескольких слов о том, как их не использовать. Шаблоны проектирования не должны применяться без разбора. Часто они достигают гибкости и изменчивости, вводя дополнительные уровни косвенности, и это может усложнить проектирование». и / или стоить вам некоторой производительности. Шаблон проектирования следует применять только тогда, когда его гибкость действительно необходима ".

Пример, который вы показываете, на самом деле ничего не делает (я не думаю, что это было предназначено, я думаю, что это было просто предназначено для примера). Само по себе, он не нуждается в шаблоне нулевого объекта. В контексте более крупной программы это возможно.

Неправильный подход состоит в том, что если он был помечен как «шаблон проектирования», он должен быть хорошим, а затем искать больше мест, в которые можно втиснуть больше шаблонов. Используйте их, когда они соответствуют программе и фактически решают проблему для вас.

Майкл Шоу
источник
7
Книга Эриха Гамма, Ричарда Хелма, Ральфа Джонсона и Джона Влиссидеса « Шаблоны проектирования: элементы многоразового объектно-ориентированного программного обеспечения ».
developerwjk
4
+1 За фактическое цитирование источника шаблонов дизайна.
Pharap
29

если я пишу более сложный код, всегда ли должен быть какой-то шаблон проектирования, которому я следую?

Нет. Шаблоны проектирования - это просто шаблоны в отношениях между объектами. Другими словами, отношения, которые используются и используются повторно достаточно часто, чтобы кто-то сказал: «Эй, мы, кажется, делаем это много, давайте дадим ему имя». Список шаблонов проектирования не был определен сразу в начале ООП, а затем передан GOF ! Они были обнаружены и в конечном итоге задокументированы, а затем популяризированы книгой.

Тем не менее, большая часть преимуществ шаблонов проектирования заключается в том, что они позволяют легче думать о разработке программного обеспечения на более высоком уровне. Они позволяют вам не беспокоиться о деталях реализации и больше думать о картине. В этом смысле они освобождают вас от мелочей, но они также могут ограничивать вас так же, как то, как вы выражаете себя, может быть ограничено словами, которые вы знаете. Таким образом, может наступить время , когда есть шаблон дизайна для большинства из того, что вы делаете просто потому , что модели , которые вы знаете , являются условия , в которых вы думаете. Держите глаза открытыми на случаи, когда вы, возможно, злоупотребляете шаблоном, и где вам может потребоваться более глубоко подумать о лучших способах выполнения действий.

Кроме того, следует понимать, что на практике вы часто не реализуете данный шаблон проектирования в такой степени, как распознаете шаблон в некотором существующем коде, например в объектной среде. Знание общих шаблонов проектирования значительно облегчает изучение того, как должна использоваться среда, потому что вы можете видеть отношения между классами в терминах, которые вы уже понимаете.

Калеб
источник
10

У шаблонов дизайна есть два преимущества

  1. Их легко описать другим разработчикам, потому что люди обычно соглашаются с тем, какие шаблоны
  2. Наши предшественники, как правило, довольно серьезно обыграли их, поэтому их сильные и слабые стороны хорошо понятны.

Цели каждой программы должны быть

  1. Оно работает. Он должен делать то, что является конечной целью, или не имеет значения, сколько шаблонов дизайна вы используете. Шаблоны проектирования ОО позволяют легко разбить проблему на части, которые легче понять, и тем легче доказать, что она работает.
  2. Это легко читать. Это где шаблоны дизайна хороши. Проблемы ОО, которые они решают, сложны. Если вы решите их «стандартным» способом, это будет проще для следующего разработчика
  3. Это легко расти. Почти 0 современных программ заканчиваются там, где все планировали. Каждая программа растет после своего первоначального выпуска. ОО паттерны, как ни странно, хорошо растут.

Это все, как говорится, обратите внимание, что каждая ссылка на шаблоны проектирования ОО "они просто хороши в работе". Они не идеальны, но они очень эффективно заполняют нишу. Используйте их, когда они работают, избегайте их, когда они не работают.

В качестве примера «сложного кода», как вы упомянули в своем вопросе, возьмите язык сценариев, который я написал. В основном это ОО с шаблонами дизайна везде. Тем не менее, когда дело дошло до написания сборщика мусора, я бесцеремонно отбросил все притворства оО, потому что конкретные вещи, которые мне нужно было сделать, были лучше смоделированы как хорошие старомодные удары битами. Во всей этой вещи не было шаблона OO до тех пор, пока он не пришел к написанию финализаторов, где OO снова стал полезной моделью. Без каких-либо помпезностей и обстоятельств код неожиданно снова вернулся к использованию методов ОО.

Используйте шаблоны дизайна всякий раз, когда они делают ваш продукт лучше; избегайте их, когда они делают ваш продукт хуже.

Корт Аммон - Восстановить Монику
источник
2
Я думаю, что последнее предложение должно быть выделено жирным шрифтом или как краткое изложение.
Pharap
5

Я немного сломаю тенденцию, потому что ответ более тонкий, чем другие ответы. Каждый класс, который вы пишете, не должен использовать шаблон проектирования, но большинство нетривиальных программ, которые вы пишете, вероятно, должны.

Нетривиальная программа без шаблонов проектирования означает:

  • Ваша программа настолько уникальна, что ни одна из ее частей не похожа на обычные проблемы, с которыми раньше сталкивались программисты. Или
  • Ваша программа содержит эти общие проблемы, но вы решили их лучше, чем раньше никто не задумывался.

Оба сценария крайне маловероятны, без обид.

Это не означает, что шаблон дизайна должен управлять вашим дизайном, или что вы должны вставить его без разбора, потому что вы думаете, что это будет выглядеть плохо, если вы этого не сделаете. Неправильный шаблон дизайна хуже, чем ничего.

Это означает, что вы должны смотреть на отсутствие шаблонов проектирования в вашей программе как на запах кода. Что-то, что заставляет вас взглянуть еще раз и пересмотреть, если ваш дизайн не может быть чище. Если в этот момент вы решите исключить шаблоны проектирования из программы, это должно быть осознанное, обоснованное решение, а не случайность.

Например, вы не говорите: «Мне нужно смоделировать дверь и замок, какой шаблон дизайна мне использовать?» Однако, если вы спроектировали его сначала без использования каких-либо шаблонов проектирования, это впоследствии должно побудить вас сказать что-то вроде: «У меня ужасно много пустых проверок в этом коде, мне интересно, есть ли шаблон проектирования, который мог бы помочь управлять ими».

Увидеть разницу? Это тонкое, но важное различие.

Карл Билефельдт
источник
5
Существует гораздо больше общих проблем (и их общих решений), чем шаблонов проектирования. Шаблоны проектирования являются каталогизированным подмножеством общих решений ОО, а не набором всех распространенных решений.
Майкл Шоу
1
Не могли бы вы определить, что вы подразумеваете под «нетривиальным», у меня сложилось впечатление, что термин «нетривиальный» был субъективным.
Pharap
1
Это субъективно. Я имею в виду ту программу, которую вы бы написали для команды на работе, требуя нескольких сопровождающих на постоянной основе.
Карл Билефельдт
Если вам повезет увидеть вашу проблему потом. Нулевые проверки, конечно. Уязвимости безопасности? Другие коварные способы сломать программу при обслуживании? Проблемы только следующий инженер раскроет? Гораздо более противный.
Джечлин
«Мне нужно смоделировать дверь и замок, каким должен быть интерфейс? Будет ли производительность частью контракта? Должен ли я использовать службу или библиотеку? Как будут передаваться ресурсы?» все должны быть заданы, и у вас должны быть ответы, которые в основном рассматриваются как шаблоны проектирования.
Джечлин
4

Сломанный вопрос. Позвольте мне дать вам новое определение шаблона проектирования, которое устранит большой ущерб, нанесенный GoF: шаблон проектирования - это хорошая практика кодирования . Вот и все.

Любой достаточно сложный модуль будет иметь несколько шаблонов проектирования. Каждый раз, когда вы кешируете, это, вероятно, шаблон с наименьшим весом, но я не собираюсь отменять вашу степень программирования, если вы не называете это так. Каждый раз, когда у вас есть обратный вызов, вы попадаете в какую-то модель события / огня / обратного вызова. и т.д. Если у вас есть слово «статический», у вас есть синглтон. Если у вас есть статический конструктор, у вас есть фабричный шаблон. Если ресурс передан вашему модулю, вы используете внедрение зависимостей.

«Шаблон дизайна» - это не пользующийся популярностью термин, не популярный в GoF, из-за которого все звучит так, будто все шаблоны находятся на одном уровне, или вам следует использовать рекомендованный врачом от 3 до 5 для каждого класса. Каждый раз, когда вы делаете что-то правильно, что кто-то сделал правильно, это шаблон дизайна . Например, A for(;;)- это общий шаблон, используемый для представления бесконечного цикла.

Вы не должны пытаться выучить кучу шаблонов дизайна. Знание программирования не индексируется шаблонами проектирования! Скорее вы должны научиться писать хороший код , читая книги, блоги и посещая конференции в своей области. Например, если вы уже используете внедрение зависимостей, но просто не пометили его, вам может быть полезно всегда использовать DI или инфраструктуру IoC. Или, если вы пытаетесь правильно кодировать события и обратные вызовы, изучите Haskell, чтобы вы были знакомы с функциональными шаблонами проектирования, и это стало легко.

И если весь ваш класс читается как одна большая вещь, которую кто-то другой сделал правильно, почему вы изобретаете велосипед? Просто используйте их вещи.

djechlin
источник
2
На каком языке for(;;)идиоматика? Это, вероятно, не лучший пример того, что кто-то сделал "правильно".
Теластин
1
@Telastyn C, C ++, Java, Javascript, C #.
Джехлин
2
Я никогда не видел, чтобы кто-то предпочитал это while(true)(или while(1)) в C, C ++, Java или C # за мои 20 с лишним лет программирования.
Теластин
1
@Telastyn stackoverflow.com/a/2611744/1339987 fwiw Я начал предпочитать while (true), потому что он выглядит более читабельным для меня.
Джехлин
1
Я всегда использую для (;;). Нет особой причины, я читал это где-то, вероятно. Мне нравится тот факт, что здесь нет переменных или констант. Во всяком случае, @Telastyn теперь вы встретили кого-то .
Муравей
0

Вы всегда должны следовать принципам проектирования ОО (например, модульность, скрытие информации, высокая сплоченность и т. Д.). Шаблоны проектирования - это относительно утонченная ниша принципов проектирования ОО, особенно если учесть принцип KISS .

Шаблоны - это решение общих проблем дизайна. Эти проблемы происходят из одного из двух мест (или из обоих): проблемное пространство (например, программное обеспечение для управления человеческими ресурсами в компании) и пространство решения . ОО-программы - это экземпляр в пространстве решений (например, один из многих способов, которыми вы могли бы разработать ОО-программу для облегчения управления персоналом).

Это не так легко узнать, когда использовать шаблон. Некоторые шаблоны являются низкоуровневыми, ближе к кодированию и пространству решения (например, Singleton, Null object, Iterator). Другие мотивированы требованиями в проблемном пространстве (например, шаблон Команды для поддержки отмены / повторения, Стратегия для поддержки нескольких типов файлов ввода / вывода).

Многие шаблоны исходят из необходимости поддержки изменений программного обеспечения в будущем. Если вам никогда не нужно вносить эти изменения, шаблон может быть чрезмерным. Примером может служить использование шаблона адаптера для работы с существующей внешней базой данных персонала. Вы решили применить Adapter, потому что текущая база данных работает с Oracle, и вы можете захотеть поддерживать NoSQL в будущем. Если NoSQL никогда не появится в вашей организации, этот код адаптера вполне может оказаться бесполезным. Смотри ЯГНИ . Поддержка вариаций, которые никогда не появляются, неправильно использует шаблон проектирования.

Fuhrmanator
источник
0

Шаблоны - это общие решения общих проблем. Мы всегда следуем некоторым шаблонам, шаблоны от GoF обращаются к наиболее повторяющимся. Это, чтобы иметь общее понимание и общий подход, известный разработчикам программного обеспечения.

Тем не менее, мой ответ - нет, но да, вы всегда следуете какой-то своей схеме. Как правильно говорит GoF-

Образец одного человека - это примитивный строительный блок другого человека.

Отличная цитата.

Syed Priom
источник
кажется, это не дает ничего существенного по сравнению с замечаниями, сделанными и объясненными в предыдущих 7 ответах
комнат
Хорошо. Обратите внимание, я сделал общее замечание ... это применимо к шаблонам проектирования как теоретическое обсуждение.
Syed Priom
«Этот сайт посвящен получению ответов . Это не дискуссионный форум ...» ( тур )
коммент
Я ответил на вопрос. Спасибо. Этот разговор заканчивается здесь.
Syed Priom
@gnat, черт возьми, это намного лаконичнее.
Джечлин
0

Когда я пишу код, я не планирую намеренно использовать столько шаблонов проектирования, сколько смогу. Но, я думаю, подсознательно, когда у меня возникает проблема с кодированием, один из шаблонов проектирования кажется подходящим, и я просто использую его. И иногда ничего не подходит. Что для меня важнее, так это написание кода, который выполняет свою работу, его легко поддерживать и расширять.

Вот статья о применении принципов OOD с использованием шаблонов проектирования, а также примеры кода (на C ++). Он показывает, как и когда применять некоторые шаблоны проектирования для написания чистого кода.

слащавость
источник
2
Эта статья была написана только вчера; Вы связаны с блогом вообще? Если это так, пожалуйста, сообщите об этой принадлежности .
Мартейн Питерс