Size: a a a

2021 March 31

SP

Sergey Protko in symfony
Chiki Briki
Че я думаю по итогу. У нас есть несколько вариантов вхождения в метод службы:
1. апи эндпоинт, принимает какие-то данные
2. внутренняя логика, которая эти данные как-то генерирует

У нас есть ДТО (для АПИ = контракт), которая создается по определенным правилам (типы, required поля и т.д.)
Во время создания ДТО мы можем развалиться.

Если мы хотим исчерпывающий отчет по ошибки для случая 1 - валидируем входные данные на момент соблюдения контракта до создания ДТО
Если человек по каким-то причинам создает невалидную ДТО в рамках внутренней логики - он получит ошибку процесса маппинга на ДТО, захочет - обработает

Дальше у нас идут правила, которые должны быть соблюдены для корректной работы метода службы. Их можно делать как через VO, возможно можно делать их через validate->(DTO) на входе и т.д.

Как итог: обьект (инстанс службы) через свой метод (проверки вызываемые в нем) должен проверять правила требуемые для конкретного юз кейса. Таким образом, как по мне, дубликация правил валидации на обоих слоях будет сведена к минимуму и риск некорректной работы сервиса тоже.

Шо скажемс?
все становится проще если на каждом уровне смотреть на валидацию с позиции "а кому это надо".

Валидация "email не должен быть пустой" - это валидация входных данных и должна она происходить на "входе". До того как ты эти данные успеешь замэпить на что-то и т.д.  Можно мэпить на DTO и валидировать если у тебя мэппинг 1:1 - иначе потом сложно понять где проблема.

В целом валидация входных данных нужна "для клиента" и тут сложность для большинства разработчиков в том что они не воспринимают код который дергает из контроллера сервис скажем как "клиент сервиса". для них клиент это мобилка или React апа там где-то.

На каждом уровне есть клиентский код который чет вызываает и на каждом уровне свои правила. + есть разница между "валидацией данных" и "проверкой инвариантов стэйта".

Словом... вся проблема в излишнем обобщении
источник

SP

Sergey Protko in symfony
в мобилке валидация обязательного поля, в апишка валидация того что поле есть в json-ке, в базе констрейнт что поле не null. Выглядит как дублирование но если разобраться "кому это надо и для чего" вдруг оказывается что все это отдельно друг от дружки
источник

ПГ

Павел Г. in symfony
Sergey Protko
все становится проще если на каждом уровне смотреть на валидацию с позиции "а кому это надо".

Валидация "email не должен быть пустой" - это валидация входных данных и должна она происходить на "входе". До того как ты эти данные успеешь замэпить на что-то и т.д.  Можно мэпить на DTO и валидировать если у тебя мэппинг 1:1 - иначе потом сложно понять где проблема.

В целом валидация входных данных нужна "для клиента" и тут сложность для большинства разработчиков в том что они не воспринимают код который дергает из контроллера сервис скажем как "клиент сервиса". для них клиент это мобилка или React апа там где-то.

На каждом уровне есть клиентский код который чет вызываает и на каждом уровне свои правила. + есть разница между "валидацией данных" и "проверкой инвариантов стэйта".

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

SP

Sergey Protko in symfony
ну самый простой и тупой вариант - когда у тебя запрос мэпится на DTO 1:1 без каких либо трансформаций вообще. Тогда ты можешь правила валидации с DTO собирать и натравливать на массив который собираешься замэпить в DTO. При этом можно еще лайфхаки делать чет типа "если у меня там public string $name то можно сразу вывести правило что тип херни string и нельзя нулы.
источник

SP

Sergey Protko in symfony
это уже вопрос изобретательности. симфони валидатор прекрасно умеет валидировать массивчики
источник

SP

Sergey Protko in symfony
я уже давно не гуглил готовых штук на эту тему - уверен они есть. У меня свои велосипеды...
источник

ПГ

Павел Г. in symfony
Sergey Protko
это уже вопрос изобретательности. симфони валидатор прекрасно умеет валидировать массивчики
Не, я больше к тому где правила валидации хранить для массива, который получаем из request. Когда я валидировал DTO я просто там прописывал анотации и запихивал ДТОшку в валидатор. Если я валидирую массив, правила нужно хранить где то отдельно. Ну либо делать в каждом DTO метод getValidatorRules - что выглядит не очень вроде.
источник

ПГ

Павел Г. in symfony
Например один из способо сейчас - это формы юзать. Но когда я делаю все это именно в контроллерах а не резолверах, я знаю какую форму в каком контроллере создать. Тут же выходит, что надо по DTO определить какая форма с правилами валидации именно в резолвере.
источник

VM

Volodymyr Melko in symfony
Павел Г.
Например один из способо сейчас - это формы юзать. Но когда я делаю все это именно в контроллерах а не резолверах, я знаю какую форму в каком контроллере создать. Тут же выходит, что надо по DTO определить какая форма с правилами валидации именно в резолвере.
В ямликах храни
источник

ПГ

Павел Г. in symfony
Volodymyr Melko
В ямликах храни
хм, а вот это интересный вариант.
источник

ПГ

Павел Г. in symfony
Volodymyr Melko
В ямликах храни
Так в ямликах - хранение валидации классов, а нужно провалидировать массив. Правда если в валидатор есть экспорт рулов, то уже все гораздо интереснее.
источник

VM

Volodymyr Melko in symfony
Павел Г.
Так в ямликах - хранение валидации классов, а нужно провалидировать массив. Правда если в валидатор есть экспорт рулов, то уже все гораздо интереснее.
Ну тогда только кастомный валидатор ;)
источник

VM

Volodymyr Melko in symfony
Но чем не устраивает мапинг на ДТО и валидация дтохи?
источник

ПГ

Павел Г. in symfony
Volodymyr Melko
Но чем не устраивает мапинг на ДТО и валидация дтохи?
Банально, что если ДТОха типизирована - то упадем на этапе мапинга, если что-то не так
источник

VM

Volodymyr Melko in symfony
catch никто не отменял
как и дефолтные значения
источник

ПГ

Павел Г. in symfony
Volodymyr Melko
catch никто не отменял
как и дефолтные значения
Так у нас выходит уже какая-то полувалидация на этапе маппинга, а потом еще и валидаци валидатором.
источник

ПГ

Павел Г. in symfony
На самом деле варианты есть, по тому же FQN искать, положить рулы рядом с DTO под определенным неймингом и норм. Просто как-то кривовато выглядит.
источник

ПГ

Павел Г. in symfony
Или в самой DTOхе писать, но в методе, чтобы можно было экспортнуть. Хотя если покопаться, наверное можно и аннотации дернуть. Просто я думаю делают как то более изящно ) колитесь ))
источник

ПГ

Павел Г. in symfony
Павел Г.
Или в самой DTOхе писать, но в методе, чтобы можно было экспортнуть. Хотя если покопаться, наверное можно и аннотации дернуть. Просто я думаю делают как то более изящно ) колитесь ))
В общем можно дернуть констрейнты из DTO, в которой прописаны рулы аннотациями и применить их к массиву. Магией попахивает и костылями, но выглядит удобно.
источник

SP

Sergey Protko in symfony
Павел Г.
В общем можно дернуть констрейнты из DTO, в которой прописаны рулы аннотациями и применить их к массиву. Магией попахивает и костылями, но выглядит удобно.
ну до typehint к пропертям можно было бы просто замэпить и завалидировать, но с тайпхинтами получаешь ошибки до валидации
источник