Объективно Хорошие ОО Принципы Дизайна - PullRequest
2 голосов
/ 14 декабря 2008

Предпосылка

Я считаю, что есть способ объективно определить «Хорошие» и «Плохие» объектно-ориентированные методы проектирования и что, как сообщество, мы можем определить, что это такое. Это академическое упражнение. Если это будет сделано серьезно и решительно, я считаю, что это может принести большую пользу сообществу в целом. Сообщество выиграет, если у нас будет место, на которое мы все можем указать: «Этот метод« Хороший »или« Плохой », и мы должны или не должны использовать его, если нет особых обстоятельств».

План

Для этого мы должны сосредоточиться на объектно-ориентированных принципах (в отличие от функциональных языков, языков на основе множеств или других типов).

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

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

Основание

Я хотел бы сделать ударение при определении «Хорошо» и «Плохо»:

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

  • «Плохо» - эта техника может работать в краткосрочной перспективе, но вскоре становится пассивом. Это сразу трудно изменить или становится более сложным со временем. Первоначальные инвестиции могут быть небольшими или большими, но они быстро становятся растущими, в конечном итоге превращаются в непогашенные, и их необходимо постоянно устранять или обходить. Оно субъективно применяется и противоречиво и может стать сюрпризом или его трудно будет распознать программистам по обслуживанию в будущем. В целом, это способствует в конечном итоге увеличению затрат на обслуживание и / или эксплуатацию продукта и препятствует или предотвращает изменения продукта. Запрещая или предотвращая изменения, они становятся не просто прямыми затратами, а альтернативными затратами и значительной ответственностью.

Стартер

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

Разделение интересов

[Краткое описание]

* +1034 * Пример

[Пример кода или другой тип]

Цель

[Объяснение каких проблем предотвращает этот принцип]

* * 1 042 Применимость * * тысяча сорок-три

[Почему, где и когда я использовал бы этот принцип?]

Исключения

[Когда бы я не использовал этот принцип или где он мог бы быть вредным?]

Возражения * * тысяча пятьдесят-одна [Обратите внимание на любые особые мнения или возражения сообщества здесь]

Ответы [ 3 ]

3 голосов
/ 14 декабря 2008

Есть несколько хорошо понятых принципов, которые могут послужить хорошей отправной точкой:

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

1 голос
/ 14 декабря 2008

Я думаю, что короткий ответ заключается в том, что «хорошие» ОО-проекты устойчивы к изменениям, с наименьшим количеством ошибок кода при любых изменениях требований. Если вы рассмотрите все обычные правила, они все склонны к тому же самому выводу.

Сложность состоит в том, что вы не можете оценить «совершенство» дизайна без контекста; Я считаю, что это теорема о том, что для любой модульности существует изменение требований, которое максимизирует разрыв, вызывая прикосновение к каждому классу в каждом методе.

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

В большинстве случаев, однако, некоторая хорошо развитая интуиция очень помогает: вещи, специфичные для устройства или платформы, меняются, бизнес-правила и бизнес-процессы меняются, в то время как реализации, скажем, арифметики, меняются очень редко. , (Нет, как вы можете себе представить, никогда. Рассмотрим, например, бизнес-систему, которая может или не может использовать арифметику BCD с поддержкой платформы.)

1 голос
/ 14 декабря 2008

Разделение концернов

Предпочтение агрегации смешанному типу наследования

Хотя функциональность можно получить путем наследования от служебного класса, во многих случаях все это можно получить с помощью члена указанного класса.

Пример (Boost.Noncopyable):

Boost.Noncopyable - это класс C ++, в котором отсутствует конструктор копирования или оператор присваивания. Он может использоваться в качестве базового класса для предотвращения копирования или назначения подкласса (это обычное поведение). Он также может быть использован в качестве прямого члена

Преобразовать это:

class Foo : private boost::noncopyable { ... };

К этому:

class Foo {
    ...
private:
    boost::noncopyable noncopyable_;
};

Пример (блокируемый объект):

Java ввела ключевое слово synchronized в качестве идиомы, позволяющей использовать любой объект в поточно-ориентированном режиме. Это может быть отражено в других языках для предоставления мьютексов произвольным объектам. Типичным примером являются структуры данных:

class ThreadsafeVector<T> : public Vector<T>, public Mutex { ... };

Вместо этого два класса можно объединять вместе.

struct ThreadsafeVector<T> {
    Vector<T> vector;
    Mutex mutex;
}

Цель

Наследование часто используется как механизм повторного использования кода. Если наследование используется для чего-либо, кроме отношения Is-A, общая ясность кода уменьшается.

При использовании более глубоких цепочек базовые классы миксина значительно увеличивают вероятность сценария «Алмаз смерти», в котором подкласс наследует несколько копий класса миксина.

Применимость * +1032 * Любой язык, поддерживающий множественное наследование. Исключения

Любой случай, когда класс mixin предоставляет или требует перегрузки членов. В этом случае наследование обычно подразумевает отношение «Реализуется в терминах», и совокупности будет недостаточно.

Возражения

Результат этого преобразования может привести к общедоступным членам (например, MyThreadSafeDataStructure может иметь общедоступный Mutex в качестве компонента).

...