День четыреста сорок седьмой. #DesignPatterns
Принципы SOLID.
1. Принцип единственной обязанности (SRP)
«У класса должна быть только одна причина для изменения»
(Мартин Р. Принципы, паттерны и практики гибкой разработки. — 2006).
В разработке ПО есть одна неизменная составляющая — неизбежность изменений. Как бы мы ни старались всё продумать, требования изменяются: из-за изначального недопонимания задачи, изменений во внешнем мире или перехода на новую технологию. Но нам важны не причины изменений, а наши возможности по адаптации системы к новым требованиям и легкость внесения изменений.
Возникает соблазн создать обобщённое решение, предусмотрев все возможные сценарии и, тем самым, предсказав любые возможные изменения. Но в реальности практически невозможно угадать, как изменятся требования, и в каком направлении система будет изменяться. А поскольку гибкость всегда приводит к увеличению сложности, то полученное решение не всегда справляется с исходной задачей и плохо поддаётся модификации.
Другой подход - использование наиболее простых решений: программная сущность (класс, модуль, метод) должна по возможности решать лишь одну задачу, но делать это хорошо. Таким образом, чем меньше у метода, класса или модуля вспомогательных задач, тем ниже вероятность случайных изменений.
В любом проекте выделяют существенную и случайную сложность. То же самое можно сказать и об изменениях. Существенные возникают из-за изменения бизнес-логики или требуемого поведения, а случайные мы вынуждены вносить во второстепенные модули из-за неудачного дизайна.
Принцип SRP предназначен для борьбы со сложностью. В небольших приложениях проектирование практически не нужно. Проблемы возникают, когда система растёт. Добавление каждой новой функции требует всё больше усилий. В крупных системах важно иметь возможность сосредоточиться на главной задаче метода/класса/модуля и выбросить из рассмотрения все второстепенные детали.
Cложность принципа в том, что понятие «обязанности» является относительным. Может ли метод проверять свои аргументы? Или вести запись в лог? Наличие или отсутствие нарушения SRP очень зависит от того, насколько сложным является каждый из описанных шагов. Метод будет нарушать SRP, если за второстепенными функциями не видно основной логики. Но класс может и не нарушать SRP, если он читает и сохраняет данные, но на каждую операцию требуется две строки кода.
Примеры нарушения SRP
1. Смешивание логики с инфраструктурой. Бизнес-логика смешана с представлением, логикой репозитория и т.п.
2. Слабая связность. Класс/модуль/метод не является цельным, и разные его части обращаются к разным подмножествам данных.
3. Выполнение нескольких несвязанных задач. Класс/модуль/метод должен быть сфокусированным на решении минимального числа задач.
4. Решение задач разных уровней абстракции. Класс/метод не должен отвечать за задачи разного уровня (например, проверка аргументов, сериализация и шифрование). Каждый из этих аспектов должен решаться отдельным классом.
Важность принципа единственной обязанности резко возрастает при увеличении сложности. Каждый раз при изменении логики нужно анализировать дизайн на соответствие здравому смыслу и принципам проектирования. Если решение перестает помещаться в голове, то пришло время разбить его на более простые составляющие, каждая из которых будет решать лишь одну задачу.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 17.
Post #543
1.23K