Table of Contents
SOLID
Принцип единственной ответственности (Single Responsibility Principle)
Существует лишь одна причина, приводящая к изменению класса.
Один класс должен решать только какую-то одну задачу. Он может иметь несколько методов, но они должны использоваться лишь для решения общей задачи. Все методы и свойства должны служить одной цели. Если класс имеет несколько назначений, его нужно разделить на отдельные классы.
Принцип открытости/закрытости (Open-closed Principle)
Программные сущности должны быть открыты для расширения, но закрыты для модификации.
Программные сущности (классы, модули, функции и прочее) должны быть расширяемыми без изменения своего содержимого. Если строго соблюдать этот принцип, то можно регулировать поведение кода без изменения самого исходника.
Принцип подстановки Барбары Лисков (Liskov Substitution Principle)
Этот принцип Барбара Лисков предложила в своём докладе “Data abstraction” в 1987-м. А в 1994-м идея была вкратце сформулирована Барбарой и Дженнет Уинг:
Пусть φ(x) — доказуемое свойство объекта x типа T. Тогда φ(y) должно быть верным для объектов y типа S, где S — подтип T.
В удобочитаемой версии повторяется практически всё, что говорил Бертранд Майер, но здесь в качестве базиса взята система типов:
- Предварительные условия не могут быть усилены в подтипе.
- Постусловия не могут быть ослаблены в подтипе.
- Инварианты супертипа могут быть сохранены в подтипе.
Роберт Мартин в 1996-м дал другое определение, более понятное:
Функции, использующие указатели ссылок на базовые классы, должны уметь использовать объекты производных классов, даже не зная об этом.
Попросту говоря: подкласс/производный класс должен быть взаимозаменяем с базовым/родительским классом.
Значит, любая реализация абстракции (интерфейса) должна быть взаимозаменяемой в любом месте, в котором принимается эта абстракция. По сути, когда мы используем в коде интерфейсы, то используем контракт не только по входным данным, принимаемым интерфейсом, но и по выходным данным, возвращаемым разными классами, реализующими этот интерфейс. В обоих случаях данные должны быть одного типа.
Принцип разделения интерфейса (Interface Segregation Principle)
Нельзя заставлять клиента реализовать интерфейс, которым он не пользуется.
Это означает, что нужно разбивать интерфейсы на более мелкие, лучше удовлетворяющие конкретным потребностям клиентов.
Как и в случае с принципом единственной ответственности, цель принципа разделения интерфейса заключается в минимизации побочных эффектов и повторов за счёт разделения ПО на независимые части.
Принцип инверсии зависимостей (Dependency Inversion Principle)
Высокоуровневые модули не должны зависеть от низкоуровневых. Оба вида модулей должны зависеть от абстракций.
Абстракции не должны зависеть от подробностей. Подробности должны зависеть от абстракций.
Проще говоря: зависьте от абстракций, а не от чего-то конкретного.
Применяя этот принцип, одни модули можно легко заменять другими, всего лишь меняя модуль зависимости, и тогда никакие перемены в низкоуровневом модуле не повлияют на высокоуровневый.