С концепцией запроса в целом разобрался, что делать с результатами работы Интерактора? В каком формате возвращать результат, как учесть ошибки и валидацию данных? Думаю, что Интерактор должен возвращать объект Ответа. Мотивация аналогична объекту Запроса: четкая структура ответа и типизация, более абстрактный Интерактор не должен заботиться о конкретном формате возвращаемых данных, требуемом клиентской стороной. С другой стороны, клиент будет знать структуру возвращаемых данных и сможет с ними работать.
Следующий вопрос: как возвращать объект Ответа? Вижу два основных варианта. В первом объект создается внутри интерактора и после заполнения данными отправляется наружу. Во втором в интерактор передается пустой (установленный по умолчанию) объект ответа, который внутри заполняется данными. Какой вариант предпочтительнее? Это зависит от того, что нужно делать в контроллере с этим объектом. Если понадобится расширять и дополнять его, то предпочтителен второй вариант. Такая возможность полезна, ведь одни и те же данные часто нужно возвращать на клиент в разном виде. Поэтому для контроллеров может понадобиться дополнительная функциональность, облагораживающая данные для показа в конкретном шаблоне.
Сначала я написал реализацию с созданием объекта ответа внутри интерактора (коммит). Базовый класс Response
содержит поля для статуса ответа и ошибок, если таковые возникнут. Плюс геттеры и сеттеры для статуса. Это общая функциональность, которая нужна всем классам-наследникам. В последних задаются конкретные поля для возвращаемых данных.
По некотором размышлении подумалось, что правильнее использовать второй вариант - создание чистого объекта ответа на клиенте (в контроллере) и передача его для заполнения в интерактор. Основную роль в этом убеждении сыграли вышеприведенные соображения плюс соображения о предпочтении интерфейсов реализациям. Так и переделал.
И еще. В интеракторе создания задачи разделил само по себе создание объекта-задачи и добавление его в репозиторий (коммит). По-хорошему, создание объекта и сохранение его не связаны между собой по смыслу. Не всегда созданный объект нужно сохранять, можно, например, вернуть его клиенту в ответ на запрос. Поэтому добавление созданного объекта будет производиться при помощи метода Repo\TaskInterface::add(Entity\Task $task)
. За создание объекта отвечает метод Repo\TaskInterface::create(...)
(коммит). Он позволяет избежать явного создания Сущности там, где она нужна.
Итак, использование отдельного объекта Ответа унифицирует формат возвращаемых в контроллер данных и отвязывает эти данные от типа ответа клиенту.