SOLID на практике — принцип единственной ответственности

Принцип единственной ответственности (Single Responsibility Principle — SRP, буква S в аббревиатуре SOLID), описанный Робертом Мартином, гласит: «Класс должен иметь только одну причину для изменения».

Обратите внимание на следующий код:

В примере приведён метод сохранения изменений в записи типа Topic. Однако этот метод выполняет слишком много действий: валидацию полученных данных, поиск существующего объекта типа Topic, проверку прав доступа пользователя на этот объект, применение и сохранение изменений. И все эти действия могут меняться независимо друг от друга.

Следуя логике принципа единственной ответственности, нам следует выделить работу с источником данных, валидацию и проверку прав доступа, как минимум, в отдельные методы, а наиболее правильно — в отдельные классы.

Выделение логики в отдельные методы

В первом варианте мы разделим логику между методами класса TopicService. Кроме этого данные, получаемые методом update, логично будет инкапсулировать в одном классе:

В результате выделения логики валидации, работы с источником данных и проверки прав доступа в отдельные методы должен получиться примерно такой код:

Теперь этот код на уровне методов соответствует принципу единственной ответственности, чего не скажешь о всём классе TopicService. Не смотря на то, что методы findOneById, save, checkAccess и validate скрыты от внешнего наблюдателя, класс всё равно выполняет много действий.

Однако даже при этом код уже более удобен для понимания, а так же пригоден для повторного использования.

Выделение логики в отдельные классы

При выделении логики валидации, проверки прав и работы с источниками данных в отдельные классы, код приложения станет ещё удобнее и понятнее.

Таким образом мы получим класс, работающий с источником данных:

Класс, выполняющий валидацию UpdateTopicAction:

Класс, проверяющий доступ пользователя к объекту Topic:

Итоговый вид нашего сервиса будет следующим:

Таким образом мы на практике применили принцип единой ответственности.