Search
Write a publication
Pull to refresh
5
0
Андрей Яценко @yzen_dev

Пользователь

Send message
DTO не для проверки наличия переменных и их типов.


Да, DTO для прокидывания данных между слоями/процессами.
В моем случае я использую в отдельных сервисах. Которые на вход принимают DTO и делают свою работу на основе его, никак завися от внешних сущностей.
Это модель для общения между слоями.

Я могу просто объявить метод с переменными и код будет чище и понятнее.
function calculate(float $sum, float $percent, int $period) {}


Согласен, с таким примером можно и так указать. Не нужно усложнять простые методы. Пример привел просто для наглядности. Также в начале статьи я специально написал, что речь идет про код, где если у метода больше 2-3 входных аргументов многие делают (array args). Т.е. подразумевая что такое решение с массивом плохое. Так что простые методы где аргументы передаются по порядку (float $sum, float $percent, int $period) я не ставил под сомнение:)

Если рассмотреть создание какого-нибудь пользователя. У нас может быть фамилия, имя, отчество, дата рождения, почта, пароль, номер телефона.
Вы же не будете все 7 аргументов указывать во входных атрибутах?
И опять же у сущности может быть их десятки. И вот в таком кейсе хорошо использовать подход с DTO.

Из-за ублюдочности недоделанной системы типизации php назад можно вернуть dto, если возвращаемых параметров больше одного


Можно уточнить, а в чем все-таки «ублюдочность» типизации? И что плохого в том, что назад мы можем получить тоже DTO? Это ведь конкретная модель, с которой мы потом продолжаем работать, не пойму.
Видимо пример с использованием реквестов многих сбил с основного назначения пакета. Ну это моя первая статья, учту на будущее.

Это не какой-то новый слой, и он никак не зависит от реквеста. Допустим у вас есть бизнесовый сервис, который должен посчитать комиссию по кредиту. В аргументы ему необходимо передать процент годовых, сумма кредита, и период на который запрашивается сумма. Если бы вы использовали подход передачи аргументов массивов, то вам пришлось бы проверять наличие каждого ключа, также, даже если ключ и будет, он может быть любого типа, что тоже нужно проверить.
При описанном подходе вы создаете DTO:

class CalcDTO
{
    public float $sum;
    public float $percent;
    public int $period;
}


Как мы видим, объект всегда будет содержать 3 параметра нужного нам типа. Вы не сможете инициализировать его с другим типов или не указать какое то поле. И тогда вы просто передаете эту DTO в калькулятор, который уже точно знает что все аргументы валидные.

Отвечая на вопрос в чем же чистота:
— Сервис становится типизированным;
— Сервис работает с валидными данными которые приходят к нему в DTO;
— Нам не нужно проверять наличие ключей;
— Исключается возможность передачи неверного типа;

Просто не всегда же все зависит от реквеста:) Поэтому тут скорее реквест требует данные которые необходимы для сервиса, а мой пакет поможет легко преобразовать запрос в нужную DTO.
Если в методе transform вы ручками переписываете все, что прилетело в Request — то где же профит?

Вы переписываете только в случае если наименования параметром из запроса отличается он наименований в DTO. В большинстве же случаев наименования все таки идентичные. Что в запросе firstName, что в сервисе по созданию firstName.

А разве DTO должен реализовывать валидацию?
Если вы используете типизированный подход с declare(strict_types=1), то тогда это сделает пыха, и не даст вам присвоить не верный тип.
По поводу spatie был не прав, выше уже написал об этом.

Я не особо вижу профита в промежуточном объекте вашего ClassTransformer'a для DTO который в целом при такой реализации выступает своего рода фабрикой DTO, при этом не обязательно, чтобы объект был DTO ведь скормить ему можно все что угодно, при этом отсутствует валидация типов.


В этом и суть была, то что я могу скормить туда массив или объект любого класса, а ClassTransformer автоматически преобразует в нужный мне объект DTO.

Валидация типов зависит от вас. Если вы укажите параметру $name тип string, и в dto укажите declare(strict_types=1); то при попытке присвоить имени какой нибудь объект пхп скажет хрен что так нельзя.
> Entities annotation for PHP Database driver

Но ведь тут совсем другой кейс.
Мой пакет только преобразует набор данных к нужному DTO классу.
Да, вы правы. Первая проблема была все-таки плохого ресерча, из-за которого не смог оценить все текущие решения:( Поэтому сначала запилил свое, а потом только наткнулся на решение от spatie.

Я изначально старался сделать удобнее работу внутренних сервисов, а не получение данных из запроса. Допустим у вас есть бизнесовый сервис, который должен сгенерировать заявление на увольнение. В аргументы ему необходимо передать ФИО работника, должность и дату. В данном случае я могу легко привести любой набор данных, как передать это из запроса:

$dto = ClassTransformer::transform(DismissedEmployee::class, $request);
$user = $this->userService->dismiss($dto);


так и сразу сущность из базы:
$dto = ClassTransformer::transform(DismissedEmployee::class, User::find(1));
$user = $this->userService->dismiss($dto);


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

Так что пока не вижу ничего плохого в еще одном решение. Буду стараться развивать пакет, и может быть у меня появятся какие-нибудь свои фичи:)
По-моему, это обертка ради обертки. Подобные реализации избыточны.
Сократить условный 'required|string' ради чего? Всю локализацию ошибок я и так могу отдельно описать.
Не стоит забывать про принцип KISS :)

Information

Rating
Does not participate
Location
Краснодар, Краснодарский край, Россия
Date of birth
Registered
Activity