Многие компании при приеме на должность разработчика требуют от специалистов знания SOLID. Однако многие разработчики считают, что это всего лишь набор практик при разработке, не зная на самом деле стоящей за ним теории.
Принципы S.O.L.I.D., аббревиатура с инициалами принципов, обсуждаемых ниже, направлены на организацию функций и структур данных для облегчения разработки и эволюции программного обеспечения. Цель этих принципов – создать код, который терпимо относится к изменениям, прост для понимания и является основой компонентов, которые можно использовать в различных системах.
S – Принцип единой ответственности (SRP)
O – Принцип открытости-закрытости (OCP)
L – Принцип замещения Лискова (LSP)
I – Принцип разделения интерфейсов (ISP)
D – Принцип инверсии зависимостей (DIP)
Каждый из этих принципов будет подробно рассмотрен ниже.
SRP: Принцип единой ответственности
Этот принцип показывает, что класс должен быть специализирован на одном предмете и иметь только одну ответственность. Другими словами, класс должен иметь единственное действие для выполнения.
Роберт МАРТИН (2017) переформулирует общепринятое описание, что модуль должен иметь только одну причину для изменения, и утверждает, что SRP должен быть описан как модуль, который должен отвечать только за одного действующего лица. Этот действующее лицо представляет собой пользователя или заинтересованную сторону, которая является “причиной для изменения” в первоначальном определении. Термин модуль может быть определен как исходный файл или целостный набор функций и структуры данных.
Нарушение этого принципа может привести к тому, что класс возьмет на себя несвойственные ему обязанности, повысит уровень связанности, создаст трудности при реализации автоматизированных тестов и затруднит повторное использование кода.
OCP: принцип открытости-закрытости
Этот принцип был создан Бертраном Мейером (1997) и гласит, что программное обеспечение должно быть открытым для расширения, но закрытым для модификации. То есть, когда в систему необходимо добавить новые функции, ее нужно расширить, не изменяя исходный код.
Согласно MARTIN (2017), OCP является одной из движущих сил в архитектуре систем, это самый важный принцип объектной ориентации. Для достижения цели упрощения системы без того, чтобы это изменение вызвало большие последствия, необходимо разделить систему на компоненты. Эти компоненты организуются в иерархию зависимостей, чтобы защитить высокоуровневые компоненты от изменений, вносимых в компоненты более низкого уровня.
LSP: принцип замещения Лискова
Принцип подстановки Лискова был определен Барбарой Лисковой и говорит об использовании свойства подстановки в качестве основы. Это свойство описывается доказательством:
если для каждого объекта o1 типа S существует объект o2 типа T такой, что для всех программ P, определенных в терминах T, поведение P не изменяется при замене o1 на o2, то S является подтипом T (MEYER, 1997).
Другими словами, LSP утверждает, что если S является подтипом T, то объекты типа T в программе могут быть заменены объектами типа S без необходимости изменения свойств этой системы.
LSP стал более широким принципом объектно-ориентированного проектирования, который может быть применен к интерфейсам и реализациям. Этот принцип говорит нам, что реализации должны соответствовать какому-то контракту. Применение LSP важно, поскольку пользователям нужны хорошо определенные интерфейсы и возможность заменить реализацию интерфейсов.
Этот принцип необходимо применять к архитектуре, так как нарушение заменяемости может загрязнить архитектуру системы большим количеством лишних механизмов.
Некоторые примеры того, что может произойти при нарушении этого принципа, следующие:
- выброс неожиданного исключения;
- переопределить или реализовать метод, который ничего не делает;
- возвращать значения типов, отличных от базового класса.
ISP: Принцип разделения интерфейсов
Этот принцип показывает, что класс не должен быть вынужден реализовывать интерфейсы и методы, которые он не будет использовать, то есть лучше создавать более специфические интерфейсы, чем иметь большой общий интерфейс. Классы не должны зависеть от того, что им не нужно.
Этот принцип используется в архитектуре, чтобы избежать зависимостей модулей с большим количеством ненужных элементов. Это актуально как на более высоких, так и на более низких архитектурных уровнях, поскольку, например, зависимости от исходного кода могут без необходимости заставлять перекомпилировать и переразвертывать систему.
DIP: принцип инверсии зависимостей
О принципе инверсии зависимостей MARTIN (2017) утверждает, что наиболее гибкими системами являются те, в которых зависимости исходного кода относятся только к абстракциям, а не к конкретным элементам.
В общем, он гласит, что ни один класс или функция не должны быть озабочены тем, как выполняется определенная вещь. Некоторые классы, такие как класс String, являются конкретными, поэтому было бы неинтересно заставлять их быть абстрактными. Однако эти классы очень стабильны, поэтому изменения в них происходят очень редко и контролируются, так что вам не нужно беспокоиться об этих изменениях. Конкретные классы терпимы, потому что известно, что они не будут меняться.
Применяя Clean Architecture, модули высокого уровня не должны зависеть от модулей низкого уровня, оба должны зависеть от абстракции. Абстракции не должны зависеть от деталей, но детали должны зависеть от абстракций.
Выводы
SOLID – это не просто еще одна строчка в требованиях компаний при поиске профессионалов, это необходимый набор хороших практик.
Когда эти принципы применяются к системам, они становятся более структурированными, целостными и более гармонично масштабируемыми, что также является основой “чистой архитектуры”.
Каждый хороший профессионал должен стремиться глубже изучить принципы SOLID, применять их в своей повседневной жизни и распространять их среди своих команд. Передовой опыт должен распространяться и применяться.
Ссылки
- МАРТИН, Роберт К. Чистая архитектура: Руководство ремесленника по структуре и проектированию программного обеспечения. 1-е изд. США: Prentice Hall Press, 2017. ISBN 0134494164.
- MEYER, Bertrand. Object-Oriented Software Construction. 2. ed. Upper Saddle River, NJ: Prentice Hall, 1997. ISBN 978-0-13-629155-8.