Вчера наткнулась на интересную статью, которая рассказывает о принципах SOLID и подкрепляет все это забавными картинками. На мой взгляд она достаточно понятно и наглядно объясняет смысл принципов, чего вполне достаточно для первого знакомства с ними. Поэтому решила сохранить статью на память в вольном переводе.
Если вы знакомы с объектно-ориентированным программированием, то вы, вероятно, слышали и о принципах SOLID.
Этими пятью принципами необходимо руководствоваться и соблюдать, чтобы разрабатываемое программное обеспечение было проще поддерживать и расширять. Создал принципы Роберт С. Мартин в 2000 году.
В интернете есть много хороших статей о принципах SOLID, но среди них крайне редко встречаются примеры в картинках. Поэтому людям, которые лучше воспринимают информацию визуально, труднее понять их смысл.
Основная цель статьи - лучше понять эти принципы, используя картинки и подчеркивая предназначение каждого из них.
Некоторые из этих принципов выглядят похожими, но несмотря на это преследуют разные цели. Можно соблюсти один принцип, при этом нарушив другой.
Чтобы упростить объяснение принципов, в статье будет использоваться слово “Класс”, но учтите, что принципы могут быть применены также к функции, методу или модулю.
Теперь приступим!
S — Single Responsibility (Принцип единственной ответственности)
У класса должна быть одна ответственность.
Если у класса много обязанностей, это увеличивает вероятность ошибок, потому что внесение изменений в одну из его обязанностей может повлиять на другие без вашего ведома.
Цель
Этот принцип направлен на разделение поведения следующим образом: если в результате изменения класса возникли ошибки, они не должны затронуть поведение других классов.
O — Open-Closed (Принцип открытости/закрытости)
Классы должны быть открыты для расширения, но закрыты для изменения.
Изменение текущего поведения класса повлияет на все остальные компоненты, использующие этот класс.
Если вы хотите, чтобы класс выполнял больше функций, идеальным подходом является добавление новой функции к уже существующим, а не их изменение.
Цель
Этот принцип направлен на расширение функциональности класса без изменения его текущего поведения. Это сделано для того, чтобы избежать появления ошибок везде, где используется класс.
L — Liskov Substitution (Принцип подстановки Барбары Лисков)
Если S является подтипом T, то объекты типа T в программе могут быть заменены объектами типа S без каких-либо изменений желательных свойств этой программы.
Когда дочерний класс не может выполнять действия, которые заложены в родительском классе, это может вызвать ошибки.
Если у вас есть класс и вы создаете из него другой класс, то он становится родительским, а новый класс - дочерним. Дочерний класс должен уметь делать все, что может делать родительский класс. Этот процесс называется наследованием.
Дочерний класс должен уметь обрабатывать те же запросы и возвращать тот же результат, что и родительский класс, либо он может возвращать результат того же типа.
На рисунке видно, что родительский класс приносит кофе. При этом дочерний класс может принести капучино, потому что это один из видов кофе. Но его не поймут, если вместо кофе он принесет воду.
Если дочерний класс не соответствует указанным требованиям, это означает, что он полностью изменен и нарушает принцип Барбары Лисков.
Цель
Этот принцип направлен на обеспечение согласованности родительского и дочернего классов, чтобы они могли использоваться одинаково и без каких-либо ошибок.
I — Interface Segregation (Принцип разделения интерфейса)
Программные сущности не должны зависеть от методов, которые они не используют.
Когда класс используется для выполнения действий, которые не являются полезными, это расточительно и может привести к неожиданным ошибкам, так как класс может не уметь выполнять эти действия.
Класс должен выполнять только те действия, которые необходимы для выполнения его роли. Любое другое действие должно быть полностью удалено или перенесено в другое место, если в будущем оно может быть использовано другим классом.
Цель
Этот принцип направлен на разделение набора действий на более мелкие наборы, чтобы класс выполнял только тот набор действий, который необходим для его работы.
D — Dependency Inversion (Принцип инверсии зависимостей)
- Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба типа модулей должны зависеть от абстракций.
- Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Во-первых, давайте опишем термины, используемые в формулировке принципа более простыми словами.
Модуль верхнего уровня - класс, который выполняет действие с помощью инструмента.
Модуль нижнего уровня - инструмент, необходимый для выполнения действия.
Абстракция - интерфейс, который соединяет два класса (модуля).
Детали - то, как работает инструмент.
Этот принцип говорит, что класс не следует объединять с инструментом, который он использует для выполнения действия. Скорее, он должен быть объединен с интерфейсом, который позволит инструменту подключаться к классу.
Это также говорит о том, что и класс, и интерфейс не должны знать, как работает инструмент. Однако инструмент должен соответствовать спецификации интерфейса.
Цель
Этот принцип направлен на уменьшение зависимости класса высокого уровня от класса низкого уровня путем введения интерфейса.
Истоник - The S.O.L.I.D Principles in Pictures (Medium).