Как стать автором
Обновить

Комментарии 8

Подобные DTO я применяю при передаче данных от контроллера (MVC) к модели (MVC) в виде слоя сервисов приложения (DDD), но не в самом домене. Обычно объект запроса десериализируется и валидируется даже без написания хотя бы строчки кода (аннотации — не код :) ) и передается в сервис приложения типа DelegateClientToManagerService->execute();, которые уже с его помощью ищет клиента и менеджера в репозиториях и вызывает метод $client->delegateManagmentTo($manager). Так, по-моему, модель гораздо чище, в неё не протекает ничего из приложения, только термины бизнеса, где обычно нет выражение типа «запрос на передачу клиента новому менеджеру», есть «передача клиента менеджеру». (не буду заострять внимание, что передача клиента от одно менеджера к другому обычно не ответственность клиента, а или одного из менеджеров, либо их начальника вообще, а сам клиент сущность подневольная и менеджера ему именно назначают извне, пускай Client::assignNewManager($manager), но по сути это будет обычный сеттер).
И, да, не считаю нужным вводить в модель кто и когда её создавал и модифицировал, если это делается только для административных целей, а напрямую в бизнес-процессах не участвует. А если участвует (дата платежа и кассир, например), то для этого отдельные поля типа Payment::date и Payment::cashier, в которых как правило инфа из логов дублируется, но не всегда, то задним числом провести нужно, то за кассира создать — тогда в бизнес-сущностях отражается бизнес-информация, а в логирующих — фактическая.
И, да, не считаю нужным вводить в модель кто и когда её создавал и модифицировал, если это делается только для административных целей

Согласен с вами. Об этом я и написал в статье. В данном случае лучше использовать лог-файл и вынести логирование за пределы сущности, например в обработчики доменных событий. Я привел это только как пример.


Но, как я уже говорил, логирование на уровне сущностей может быть нужно для голосований, если мы хотим ограничить количество голосов от одного пользователя. Если голосовать могут только авторизированные пользователи, то мы привязываем голос к пользователю по его ID, а если могу и анонимные, то нужно генерировать GUID на основе IP и User-Agent.


Еще дата создания сущности может быть нужна для применения миграций, когда нам нужно например, изменить что-то в записях которые были созданы после 2017-01-01. Можно конечно извлечь эту информацию из лога, но это очень трудоемко.


А вот еще один реальный бизнес-процесс: удалять из бд все записи старше 6 месяцев. Без знания даты создания сощности это сделать невозможно.


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


Ну и на последок, приведу пример использование DTO на примере счетчика просмотров:


class Video
{
    public function view(ViewRequest $request)
    {
        if ($request->getVideo() !== $this) {
            throw new \InvalidArgumentException();
        }

        $this->total_views++;

        return new View($request);
    }
}

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


Эти навороты делаются для сохранения консистентности данных, то есть чтобы нельзя было в любом месте программы инкрементировать просмотр без реального просмотра.

Обычно объект запроса десериализируется и валидируется даже без написания хотя бы строчки кода

С этого момента можно поподробнее?

FOSRestBundle и ко.

"...private int $id;
private string $name..."
Разве PHP поддерживает явную типизацию?

Спасибо за замечание.
Поспешил я, RFC не приняли.
Я пока еще на 5.6 и путаюсь еще в нововведениях 7.x

Еще один аргумент в пользу использования геттеров и сеттеров в DTO

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории