Как реализовать принцип единственной обязанности?

Добрый день!
Имеется класс ProductController и в нем метод add, те добавление продукта. Я так понимаю, что в этом методе должно быть только добавление товара в БД, согласно одному из принципов SOLID.
Но у меня получается, что после добавления товара и его характеристик в БД, используя id добавленного товара, еще реализуется ряд дополнительных методов и запросов, нужных для формирования фильтров в магазине.
Подскажите, пожалуйста, как мне это разнести по разным методам или классам, как сформировать абстракцию, а то пока все в лоб идет.
  • Вопрос задан
  • 1062 просмотра
Пригласить эксперта
Ответы на вопрос 5
FanatPHP
@FanatPHP
Чебуратор тега РНР
Это хороший вопрос.

Начнем с того, что согласно принципу единственной обязанности в контроллере никакого добавления в БД быть не должно.
Контроллер, вообще, это самая ничтожная часть веб-приложения. Его задача - получить данные из НТТР запроса и передать их в модель и потом передать ответ браузеру. Тупо "подай-принеси".
А вот модель уже и должна записывать в базу, проверять валидность данных и совершать все прочие телодвижения.

чтобы сформировать абстракцию, надо знать задачу не на уровне огрызка туманной фразы, "ряд дополнительных методов и запросов, нужных для формирования фильтров в магазине". Что за запросы? При чем здесь фильтры вообще? Как реализован интерфейс с БД - это ОРМ, прямая работа с БД, что-то ещё?

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

То есть контроллер дергает валидатор и смотрит ответ.
Если есть ошибка валидации, то показывает форму обратно
Если ошибок нет - дергает сервис на добавление товара и потом редиректит куда-нибудь

А сервис уже выполняет все те действия, которые необходимы при добавлении товара.

В принципе, валидацию тоже можно в сервис, но тогда надо продумать обратную коммуникацию с контроллером.

Самое главное что тут надо понимать - что Модель - это не интерфейс по взаимодействию с одного класса с одной таблицей в БД (как это до сих пор считается большинством), а вся совокупность логики - классов и модулей - реализующих бизнес-логику приложения. То есть, в модель входят и мапперы, и сервисы, и репозитории и все что угодно - кроме интерфейсов взаимодействия с внешним миром, таких как контроллеры.
Ответ написан
php666
@php666
PHP-макака
Принцип единой ответственности не означает реализацию в виде одного действия или одной строчки кода.
метод add добавляет, что он еще там вызывает - не суть важно. главное конечная цель. остальное - лишь вспомогательные механизмы, которые если нужны для добавления - то никто не запрещает их использовать.
Ответ написан
@developer007
Контроллер дергает сервис у которого есть методы для работы с товаром.
ProductService->addProduct(...)

если в этот ProductService сделаете добавление/удаление комментариев к продукту то это и есть нарушение принципа единственной ответственности
Ответ написан
@red-barbarian
Совет прочитать роберт мартин чистая архитектура
Хотя бы главу о SRP
Обратить внимание "Мартин определяет ответственность как причину изменения и заключает, что классы должны иметь одну и только одну причину для изменений." Обратить внимание когда допускается все оставить в одном классе и когда желательно разделить класс.

Пока мало опыта разбивать на слои как в примерах чистой архитектуры (в интернете достаточно)
Или набивать шишки и думать почему я не сделала так как это было в примерах)
Помнить цель солид очень прагматична - сделать код который легко сопровождается. Всегда об этом помнить.
Ответ написан
Комментировать
bitniks
@bitniks
Go/PHP/Symfony developer
Как уже выше написали, всю бизнес логику лучше разместить на уровне модели, а контроллер оставить "тонким".

Чтобы не нарушать принцип единственной ответственности, можно использовать паттерн Наблюдатель. Модель после добавления товара будет создавать событие, на которое смогут подписаться другие компоненты приложения. В результате код, ответственный за разные действия, будет находится в разных сервисах системы, и при этом слабо связан между собой
https://refactoring.guru/ru/design-patterns/observer
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы