Denis
я отдельно и делаю, там несколько каскадов валидации
Denis
самый первый - схема, далее айдишники и все такое прочее
Aleksei (astynax)
@catamorphism надо ваять экзампл, походу :)
И вИдение там отразить
Denis
оба можно делать в ValidationT ErrorType m a, где ErrorType это что-то предсказуемо сериализуемое в ошибку
Denis
@astynax ну я так то в курсе что документации нифига нет, руки так и не дошли
Denis
надо конечно
Aleksei (astynax)
Может я экзампл накатаю - на скучных докладах в Минске себя займу :)
Leonid 🦇
ну а что у тебя приходит в функцию которая таки "делает" что-то? рекорд или жсон с шематиками вашими?
Aleksei (astynax)
Рекорд
Denis
смотри, в сервантохендлер приходит изоморфное json значение со схемой типе
Denis
JsonRepr MySchema
Leonid 🦇
ну вот, она лезет в базу и узнает что айдишника такого и нет. и как она рапортует? Ей значит нужно знать как поля именуются
Denis
на нем прогоняется валидация для схемы, далее кастомная валидация, далее конвертится во все что угодно(последние два пункта можно в любом порядке и там it depends)
Leonid 🦇
у вас логика же не в хендлерах
Denis
у меня требование такое: я хочу чтобы ошибки в ответе json-овом соответствовали тоже определенной схеме
Denis
поэтому мне важно получить по результату валидации что-то 1) предсказуемо сериализируемое 2) соответствующее схеме 3) по возможности красивое(это сложнее, где-нибудь какой-нибудь show в поле да проскакивает)
Leonid 🦇
я в итоге сделал кучу ADT с конструкторами в стиле HuitaUserIdDoesNotExit | HuitaTargetSomethingInBadState. фронтендер один чёрт это игнорирует и сам валидирует :(
Denis
в общем два мотивирующих юзкейса для validationt это 1) валидация крупных форм и запросов, где хочется агрегировать весь список проблем по ключам/jsonpath/xpath 2) валидация непосредственно схем, которая по сути как п.1, но без доменно-специфичных проверок
melvin
полиморфизм можно как то описать в математической нотации?
Denis
кванторами всеобщности
Leonid 🦇
@catamorphism ну, по моему мнению, валидашка форм и запросов будет без IO. А потом проверки в проблемной области уже будут стучать в бд.
Leonid 🦇
ну и валидашка форм суть парсинг
melvin
по сути полиморфизм это множество отображений из полиморфных типов в некоторый тип?
Denis
я так и делаю в принципе
Leonid 🦇
иначе не отделить механизм RPC от логики
Denis
ValidationT ErrorMapWhatever Identity a
Denis
а следующий либо в m каком-то, либо в ValidationT ErrorMapWhatever m a
Leonid 🦇
единственный бонус тут в том что ошибки покрасивее, не то что Aeson выдаст
Denis
я считаю что формат ошибок должен быть максимально предсказуемым, а не как получится
Leonid 🦇
Ну так во вторую ступень уже придет "бизнесс" объект, не?
Denis
т.к. клиенты вешают всякие обработчики на это
Leonid 🦇
это да
Denis
в разных случаях, наверное, по разному удобнее
Denis
мне нравится что получается четкий decoupling представления API от внутреннего
Leonid 🦇
у меня в общем то считай коды для ошибок, только они текстовые и имеют вид errors = [{ code = "HuitaIsBad", title="Bad huita", detail="Huita should not be bad"}, ....]
Denis
риск сломать API специально каким-то дурацким инстансом падает многократно
Denis
мы ошибки структурой отдаем json-овой
Denis
там поля отдельные с ошибкой/детализацией
Aliester
фак
Leonid 🦇
Я к тому, что не увидили мы особого смысла в помечании в каком там поле косячное значение. Ну разве что если парсится плохо.
Denis
ну и плюс эксепшены отрабатываются так, что можно HTTP-код определенный вернуть для определенных ошибок
Denis
типа not found
Denis
или ошибки валидации
Aliester
я тут себе на голову вызвался писать реализацию перцептрона Розенблата на Prolog
Denis
@lonokhov ну вот допустим ты хочешь юзера заставить создавать секьюрный пароль
Leonid 🦇
@catamorphism вот да, тоже паттерн матчу ошибки бэкэнда что-бы 404 выдать :)
Denis
ты хочешь чтобы выполнялось 1) есть цифры 2) есть буквы 3) есть спецсимволы 4) длина достаточная
Denis
мне очень не нравится поведение когда ты сабмитишь форму и тебе приезжает ошибка 1
Leonid 🦇
(за первые 3 требования нынче бьют по рукам)
Denis
ты как юзер правишь пароль, далее приезжает со следующего запроса ошибка 2 и.т.д.
Leonid 🦇
И?
Denis
я хочу все их агрегировать и отдавать разом
Denis
Leonid 🦇
Валидировать аппликативно можно и бизнесс объект
Leonid 🦇
у меня проблема с jsonpath/xpath и прочим
Leonid 🦇
оно не нужно, кмк
Denis
можно, но тогда ты теряешь путь к полю, которое валидируешь
Denis
и его нужно всякими разными способами восстанавливать и протаскивать в обе стороны
Leonid 🦇
ну и чёрт с ним, на фронте путь можно восстановить из ошибки
Leonid 🦇
/me восстаёт против принятых норм HTTP-RPC (aka RESTful)
Denis
самый главный поинт не в валидации все-таки, основной в том, чтобы представление транспортное(API или как угодно), было отвязано от внутреннего и сериализация/десериализация не зависела от всяких To/From инстансов для конкретных типов
Leonid 🦇
ну так у тебя будут рекорды для месседжей, и рекорды которые там в базе и прочая бизнесс логика. это полюбэ
Leonid 🦇
и маппинг одного в другое будет в хэндлере. а там уже бизнесс пошел
Leonid 🦇
т.е. например часть ты берешь из путей, или хэдеров хттп в одном месте, а в другом где у тебя по вебсокетам часть апи дублируется (ну или еще как) будут из другого места брать. а бэкенд и там и там один и тот же, валидирует свои вещи типа "юзер должен быть" и "батенька, а прав то у вас нет"
Leonid 🦇
но то что parseJSON выдаёт не очень полезную ошибку я согласен. String явно не достаточно.
Leonid 🦇
пусть даже они теперь там путь пишут
Leonid 🦇
вообще я сейчас вот так json парсю, и это боль
int parse_string_array(const json_t* js, std::vector<std::string> &out)
{
if (json_is_array(js)) {
int index;
json_t* value;
out.clear();
json_array_foreach(js, index, value) {
if(json_is_string(value)) {
out.push_back(json_string_value(value));
}
else {
return -1;
}
}
return 0;
}
return -1;
}
Евгений
Alexander
ваще
kosc
Ух ты.
kosc
Почти что "во плоти" 😆
Aliester
во слове
Denis
тот самый человек, который пользуется гентой
Denis
это как в анекдоте: “так вот кто купил второй!”
кана
kosc
Я думаю, тут есть ещё пользователи генты.
kosc
И тишина....
kosc
И вот эта круглая штука, перекати-поле, бежит из одного края чатика в другой.
Евгений