Вам не обязательно строго следовать этим принципам, и за их нарушение не предусмотрено никаких религиозных наказаний. Но вы должны воспринимать эти принципы как сигнал тревоги. Если один из них будет нарушен, прозвучит сигнал тревоги.
(1) Все данные должны быть скрыты внутри класса, в котором они расположены.
(2) Пользователи класса должны полагаться на общий интерфейс класса, но класс не может полагаться на своих пользователей.
(3) Минимизируйте сообщения в протоколе класса.
(4) Реализовать самый простой общедоступный интерфейс, понятный всем классам [например, операции копирования (глубокое копирование и поверхностное копирование), оценка равенства, правильный выходной контент, анализ описания ASCII и т. д.).
(5) Не помещайте детали реализации (например, частные функции, размещающие общий код) в общедоступный интерфейс класса. Если два метода класса имеют общий фрагмент кода, вы можете создать частную функцию, которая предотвратит использование этого общего кода.
(6) Не нарушайте публичный интерфейс класса вещами, которые пользователи не могут использовать или которые им не интересны.
(7) Между классами должна быть нулевая связь или только производные отношения связи. То есть один класс либо не имеет ничего общего с другим классом, либо использует только операции в публичном интерфейсе другого класса.
(8) Класс должен представлять только одну ключевую абстракцию. Все классы в пакете должны быть совместно закрыты при изменении однотипных свойств. Если изменение затрагивает пакет, оно повлияет на все классы в пакете, но не окажет никакого влияния на другие пакеты.
(9) Централизуйте связанные данные и поведение. Проектировщики должны знать об объектах, которые получают данные от других объектов с помощью таких операций, как get. Такой тип поведения подразумевает, что этот эмпирический принцип нарушается.
(10) Отнесите не относящуюся к делу информацию в другую категорию (то есть поведение, заключающееся в отказе общаться друг с другом). Создавайте зависимости для обеспечения стабильности
(11) Убедитесь, что абстрактные концепции, которые вы моделируете, являются классами, а не просто ролями, которые играют объекты.
(12) Распределить функции системы максимально равномерно в горизонтальном направлении, то есть: по замыслу классы верхнего уровня должны равномерно распределять работу.
(13) Не создавайте в своей системе всемогущие классы/объекты. Будьте особенно осторожны с классами, имена которых включают Driver, Manager, System и Susystem. Планируйте интерфейс, а не реализуйте его.
(14) Будьте осторожны с классами, которые определяют большое количество методов доступа в общедоступном интерфейсе. Большое количество методов доступа означает, что соответствующие данные и поведение не хранятся централизованно.
(15) Будьте осторожны с классами, которые содержат слишком много поведений, не взаимодействующих друг с другом. Другим проявлением этой проблемы является создание множества функций get и set в общедоступном интерфейсе классов вашего приложения.
(16) В приложении, состоящем из объектно-ориентированной модели, взаимодействующей с пользовательским интерфейсом, модель не должна зависеть от интерфейса, а интерфейс должен зависеть от модели.
(17) Моделируйте, насколько это возможно, в соответствии с реальным миром (мы часто нарушаем этот принцип, чтобы соблюсти принцип распределения системных функций, избежать принципа универсального класса и централизованно размещать соответствующие данные и поведение).
(18) Удалите ненужные классы из вашего дизайна. Как правило, мы бы понизили этот класс до свойства.
(19) Удалить классы вне системы. Характерной чертой классов вне системы является то, что, абстрактно говоря, они только отправляют сообщения в системный домен, но не принимают сообщения от других классов в системном домене.
(20) Не превращайте операции в классы. Задавайте вопросы любому классу, имя которого является глаголом или производным от глагола, особенно классу, имеющему только одно значимое действие. Подумайте, следует ли перенести это значимое поведение в класс, который уже существует или еще не обнаружен.
(21) Мы часто вводим прокси-классы при создании моделей анализа приложений. На этапе проектирования мы часто обнаруживаем, что многие агенты бесполезны и их следует удалить.
(22) Минимизируйте количество сотрудников класса. Число других классов, используемых классом, должно быть сведено к минимуму.
(23) Минимизируйте количество сообщений, передаваемых между классами и сотрудниками.
(24) Минимизируйте объем сотрудничества между классами и сотрудниками, то есть: уменьшите количество различных сообщений, передаваемых между классами и сотрудниками.
(25) Минимизировать разветвление класса, то есть уменьшить произведение количества сообщений, определенных классом, на количество отправленных сообщений.
(26) Если класс содержит объект другого класса, содержащий его класс должен отправить сообщение содержащемуся объекту. То есть: отношение включения всегда подразумевает отношение использования.
(27) Большинство методов, определенных в классе, большую часть времени должны использовать большинство членов данных.
(28) Количество объектов, содержащихся в классе, не должно превышать объем кратковременной памяти разработчика. Часто это число равно 6. Если класс содержит более 6 элементов данных, вы можете разделить логически связанные элементы данных на группу, а затем использовать новый содержащий класс для содержания этой группы элементов.
(29) Пусть системные функции распределены вертикально в узкой и глубокой системе наследования.
(30) При реализации семантических ограничений лучше всего реализовывать их в соответствии с определениями классов. Это часто приводит к переполнению класса, и в этом случае ограничения должны быть реализованы в поведении класса, обычно, но не обязательно, в конструкторе.
(31) При реализации семантических ограничений в конструкторе класса поместите тест ограничения на самый глубокий уровень включения, разрешенный доменом конструктора.
(32) Если семантическая информация, на которую опираются ограничения, часто меняется, лучше поместить ее в централизованный сторонний объект.
(33) Если семантическая информация, на которую опираются ограничения, редко меняется, ее лучше всего распределить между классами, участвующими в ограничениях.
(34) Класс должен знать, что он содержит, но не может знать, кто его содержит.
(35) Объекты, имеющие литеральную область действия (то есть содержащиеся в одном классе), не должны иметь отношений использования друг с другом.
(36) Наследование следует использовать только для моделирования иерархии специализаций.
(37) Производные классы должны знать о базовых классах, а базовые классы не должны знать никакой информации о своих производных классах.
(38) Все данные в базовом классе должны быть конфиденциальными, не используйте защищенные данные. Разработчики классов никогда не должны помещать в общедоступный интерфейс вещи, которые не нужны пользователям класса.
(39) Теоретически иерархия наследования должна быть глубже, и чем глубже, тем лучше.
(40) На практике глубина иерархии наследования не должна превышать объём кратковременной памяти среднестатистического человека. Широко распространенное значение глубины — 6.
(41) Все абстрактные классы должны быть базовыми.
(42) Все базовые классы должны быть абстрактными классами.
(43) Поместите общность данных, поведения и/или интерфейса как можно выше в иерархии наследования.
(44) Если два или более классов имеют общие данные (но не имеют общего поведения), то общие данные следует поместить в класс, который включен в каждый класс, который разделяет эти данные.
(45) Если два или более классов имеют общие данные и поведение (то есть методы), то каждый из этих классов должен наследовать от общего базового класса, который представляет эти данные и методы.
(46) Если два или более классов имеют общий интерфейс (имеется в виду сообщения, а не методы), то им следует наследовать от общего базового класса только в том случае, если их необходимо использовать полиморфно.
(47) Индивидуальный анализ отображения типов объектов, как правило, неверен. В большинстве таких случаев дизайнерам следует использовать полиморфизм.
(48)Индивидуальный анализ отображения значений атрибутов часто ошибочен. Классы должны быть разделены на иерархию наследования, при этом каждое значение атрибута должно быть преобразовано в производный класс.
(49) Не моделируйте динамическую семантику класса посредством отношений наследования. Попытка смоделировать динамическую семантику с помощью статических семантических отношений приводит к переключению типов во время выполнения.
(50) Не превращайте объекты классов в производные классы. Будьте осторожны с любым производным классом, имеющим только один экземпляр.
(51) Если вы думаете, что вам нужно создать новый класс во время выполнения, сделайте шаг назад и осознайте, что вы создаете объекты. Теперь обобщите эти объекты в класс.
(52) Использование пустого метода (то есть метода, который ничего не делает) в производном классе для переопределения метода базового класса должно быть незаконным.
(53) Не путайте необязательное включение с необходимостью наследования. Моделирование необязательного включения в качестве наследования приводит к увеличению количества классов.
(54) При создании иерархии наследования старайтесь создавать повторно используемые структуры, а не повторно используемые компоненты.
(55) Если вы используете в своем проекте множественное наследование, считайте, что вы допустили ошибку. Если вы не ошиблись, нужно постараться это доказать.
(56) Всякий раз, когда в объектно-ориентированном проектировании используется наследование, задайте себе два вопроса: (1) Является ли производный класс особым типом того, что он наследует? (2) Является ли базовый класс частью производного класса?
(57) Если вы обнаружите множественное наследование в объектно-ориентированном проекте, убедитесь, что ни один базовый класс на самом деле не является производным классом другого базового класса.
(58) В объектно-ориентированном проектировании, если вам нужно выбирать между включением и ассоциацией, выберите включение.
(59) Не используйте глобальные данные или глобальные функции для учета объектов класса. Следует использовать переменные класса или методы класса.
(60) Объектно-ориентированные проектировщики не должны позволять принципам физического проектирования подрывать их логические конструкции. Однако мы часто используем критерии физического проектирования при принятии решений о логическом проектировании.
(61) Не обходите общедоступный интерфейс для изменения состояния объекта.