Делаю ToDoLog - часть 3. Response

Просмотров: 5514Комментарии: 8
Технологии

С концепцией запроса в целом разобрался, что делать с результатами работы Интерактора? В каком формате возвращать результат, как учесть ошибки и валидацию данных? Думаю, что Интерактор должен возвращать объект Ответа. Мотивация аналогична объекту Запроса: четкая структура ответа и типизация, более абстрактный Интерактор не должен заботиться о конкретном формате возвращаемых данных, требуемом клиентской стороной. С другой стороны, клиент будет знать структуру возвращаемых данных и сможет с ними работать.

Следующий вопрос: как возвращать объект Ответа? Вижу два основных варианта. В первом объект создается внутри интерактора и после заполнения данными отправляется наружу. Во втором в интерактор передается пустой (установленный по умолчанию) объект ответа, который внутри заполняется данными. Какой вариант предпочтительнее? Это зависит от того, что нужно делать в контроллере с этим объектом. Если понадобится расширять и дополнять его, то предпочтителен второй вариант. Такая возможность полезна, ведь одни и те же данные часто нужно возвращать на клиент в разном виде. Поэтому для контроллеров может понадобиться дополнительная функциональность, облагораживающая данные для показа в конкретном шаблоне.

Сначала я написал реализацию с созданием объекта ответа внутри интерактора (коммит). Базовый класс Response содержит поля для статуса ответа и ошибок, если таковые возникнут. Плюс геттеры и сеттеры для статуса. Это общая функциональность, которая нужна всем классам-наследникам. В последних задаются конкретные поля для возвращаемых данных.

По некотором размышлении подумалось, что правильнее использовать второй вариант - создание чистого объекта ответа на клиенте (в контроллере) и передача его для заполнения в интерактор. Основную роль в этом убеждении сыграли вышеприведенные соображения плюс соображения о предпочтении интерфейсов реализациям. Так и переделал.

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

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

Комментариев: 8 RSS

1 aktuba 28-06-2014 14:16

В https://github.com/AlexKupreev/todolog/blob/development/app/service/Request.php#L20 проверка не правильная. Вернет $default, если в параметре будет пустая строка или 0, например. Переделай на isset.

2 Александр Купреев 28-06-2014 14:28

Спасибо, исправил

3 aktuba 28-06-2014 17:05

Ай-ай-ай... https://github.com/AlexKupreev/todolog/blob/development/app/service/Password.php - где соль?! ))

https://github.com/AlexKupreev/todolog/blob/development/app/request/Task/Creation.php#L20 поменяй на

public function __construct(array $data)

тогда не придется лишнюю проверку делать.

4 Александр Купреев 28-06-2014 17:22

Ай-ай-ай... https://github.com/AlexKupreev/todolog/blob/development/app/service/Password.php - где соль?! ))

Это только заглушка для создания юзера, который нужен для теста, поэтому соли нет. И sha1 скорее всего не будет, если доделаю до этапа работы с пользователем.

тогда не придется лишнюю проверку делать.

В данном контексте замечание справедливое, но я не зря писал про разные форматы входящих данных. В теории это может быть и объект, который возвращает API-сервис.

5 aktuba 28-06-2014 19:58

>я не зря писал про разные форматы входящих данных

так не пойдет. должна быть прокладка, которая стандартизирует входящие данные. иначе, через какое-то время, будешь писать избыточный код в каждом методе.

6 Александр Купреев 28-06-2014 21:10

Цель данного объекта app\request\Task\Creation как раз и быть такой прослойкой - он берет произвольные входные данные и заполняет ими строго определенные свои поля. А потом из этих полей их читает бизнес-логика. Но насчет избыточного кода подумаю, спасибо.

7 aktuba 30-06-2014 23:55

>Цель данного объекта app\request\Task\Creation как раз и быть такой прослойкой

Эммм... Тогда это должен быть 1 простой класс. С кучей ifelse. По коду - это совсем другое.

>строго определенные свои поля

Какая-же это тогда прослойка, если заполняет СВОИ поля?! ))))

8 Александр Купреев 02-07-2014 10:50

Смысл такой. За бизнес-логику отвечает интерактор, за обработку запросов - контроллер. Максимальное разделение ответственности, то есть интерактор не знает о существовании и устройстве контроллера, а контроллер - интерактора. Контроллер создает и исполняет интерактор как черный ящик. И ему нужно передать бизнес-логике внешний запрос и получить от нее результат. Контроллер не знает об устройстве интерактора, о том, какие данные ему нужны. Поэтому он берет запрос, $_POST, $_GET, API или что там еще может быть, создает из него объект Request нужного класса и пихает этот объект в интерактор. Интерактор соответственно не знает, кто его запрашивает. Он знает, что ему пришел объект с нужными полями, в которых лежат данные. За то, чтобы отфильтровать входные данные и распихать их по полям, отвечает сам объект Request. В этом смысле он - прослойка. Почему для каждого интерактора нужен Request своего типа, а не один на всех - потому что один на всю систему Request будет слишком большой и должен слишком много знать. У него будет куча свойств, возникнет проблема их именования (а это одна из двух основных проблем в программировании, как известно!). А так маленький класс, легко менять, если меняются требуемые данные. Что касается дублирования кода - возможно, получится вынести основные методы в класс-родитель.

Оставьте комментарий!


Используйте нормальные имена.

     

  

Если вы уже зарегистрированы как комментатор или хотите зарегистрироваться, укажите пароль и свой действующий email. При регистрации на указанный адрес придет письмо с кодом активации и ссылкой на ваш персональный аккаунт, где вы сможете изменить свои данные, включая адрес сайта, ник, описание, контакты и т.д., а также подписку на новые комментарии.

MaxSiteAuth. Войти через loginza

(обязательно)