В первую очередь хотелось бы сказать ловите наркомана
А во-вторую: если это пустит JS разработчиков в embeded сегмент — то очень даже клёво. Разумеется это будет совершенно не так производительно как аналоги, но она далеко не везде нужна.
А сама проблема лежит глубже — REST смешивает транспортный и прикладной уровень, и подход "200 на все" эту проблему решает (правда, делая REST не нужным вообще).
а к чему это тогда? используйте RPC или что вам ближе. Топик всё-же про REST. и выбирая его как протокол взаимодействия всё же стоит придерживаться рекомендаций этого стандарта.
А так да, вас никто не держит за руки. Кто-то пилит псевдо-REST через одни POST запросы, передавая {type: GET|POST|UPDATE|etc} в теле. Кто-то отдаёт 200 на всё, даже ошибки. Кто-то делает 1 ендпоинт а все параметры переносит в query аля GET: /api/users/:id/books/ -> /api?model=users&id=:id&field=books. Каждый строчит как он хочет
Но когда я начинаю работать над уже существующим проектом, я молюсь чтобы авторы легаси использовали стандарты а не своё "видение". Ибо "видение" очень часто в итоге превращается в боль
можно в тело ответа вставлять поле errors и при это отдавать правильный статус
а можно отдавать ошибку, но "как будто не ошибку" и на клиенте обрабатывать не только успешные и провалившиеся запросы к серверу, а ещё и "немножко успешные, но чуть-чуть провалившиеся"
Кстати нет, на беке проще отдавать всегда 200 и не париться. HTTP коды вводят для улучшения удобства работы с api
например на условный POST: /users/123/im {text: 'hello'}
500 {ok: false, message: 'SMTP relay fail: code 1234', trace: ['/path/to','/bla/bla','/lib/smtp',...]} — ошибка кода. когда возник необработанные ексепшн
или 500: {ok: false, message: 'user is not activated yet'} — ошибка бизнесс-логики, когда произошла нештатная ситуация (отправлено сообщение пользователю, но он ещё не активирован)
или 404 {ok: false, message: 'user not found'} — ошибка запроса. пользователя с таким ID нету.
на клиенте все эти ошибки можно обработать адекватно. а можно и не обрабатывать но знать хотя бы что сообщение не доставлено.
а если мы на 2 и 3 случай будем отдавать 200, то клиент будет думать — а, всё ок сообщение доставлено. он даже не узнает об ошибке, если мы отдельно не пропишем обработку псевдо-успешных запросов
Это я уже запутался. Вы правы, 404 тут как раз и должен возвращаться. Можете 418 попробовать (;
А на практике у меня обычно
404 {ok: false, message: 'not found'} для отсутствия ендпоинта
и 404 {ok: false, result: null} для отсутствия соли
это меня натолкнуло на мысль что стоит подумать над отсутствием соли. вероятно я измению этот ответ в ближайшем будущем.
к слову, для правильного запроса, по которому должен возвращаться массив. например корзина. в случае отсутствия элементов у меня
200 {ok: true, result: []}
Я фулстек разработчик, с даже бОльшим опытом во фронте. так что я рассматриваю с двух сторон баррикады.
на клиенте нам важно знать получилось ли выполнить операцию или не получилось. получилось — только для статусов 200
всё остальное (и не важно, пропала сеть, неправльный урл, ошибка сервера, ошибка БЛ, да хоть апокалипсис) — это не получилось, тобишь ошибка.
Вы же предлагаете примешать некоторые ошибки к неошибкам что бы вместо одной проверки удалось/неудалось делать их кучу даже в том коде который должен выполняться когда «удалось».
вы заведомо пытаетесь усложнить код. усложнить состояние приложение. ввести ситуации когда у нас есть не только fail/success а ещё и «какбы success, но немножко fail»
8) забыли про 500х коды. И вообще про коды тут пункт ниочём. список HTTP статусов можно и на википедии посмотреть.
Мой бестпрактис касательно кодов: В самой первой версии апи сделайте поддержку 4х статусов
200 — ок
400 — неправильный запрос
404 — не найдено результатов
500 — внутренняя ошибка сервера
Этого достаточно на первое время, а если у вас есть бюджет вы всегда сможете расширить этот список. Главное — поддержать хотя бы их.
5) пагинация через link — имхо это даже бэд практис в некоторых случаях. Если мы предоставляем limit/offset (skip/size и т.п.) — то этого более чем достаточно для пагинации, и создание линков усложняет код, не привнося никакого дополнительного функционала (ведь пагинация и так есть). А вот отказываться от limit/offset в пользу линков — плохая идея. мы заведомо ограничиваем возможности клиента, не привнося ничего взамен.
7) А что за путаница у него в методах и их индепендности? и счего бы вдруг GET был индепендным? запросив одну и ту же книгу с разницей в несколько секунд, у неё может измениться статус или рейтинг. Но это уже мелочь
Думаю этот спор всё-равно ни к чему не приведёт, но я не вижу тут оверхеда...
В чём конкретно проблема того что ассерты завраплены? С клиентской стороны этого не видно, а для разработки это проще. Не приходится тащить кусок ядра в каждый ассерт в отличае от вашей идеи.
Объект создаётся только потому что с ним работать удобнее. В нём не лежит ни одной функции, и он легко сериализуется в JSON. Все ассерты находятся в прототипе который JS движок не будет пересоздавать на каждый чих.
Да, функциональщина это круто. Но тут получается функциональщина ради функциональщины.
Кроме этого, если оформить в функциональном стиле, мы получим ...
… усложнение кода библиотеки, повышение порога вход, усложнение кода клиента и стоимости его поддержки, без выйгрыша в чём либо.
Теоретически compose вместе с хитрым createComplexRule могут дать какой-то прирост в производительности по сравнению с runAssertAsMethod. Но это уж точно выглядит оверхедом и преждевременной оптимизацией
В первую очередь хотелось бы сказать ловите наркомана
А во-вторую: если это пустит JS разработчиков в embeded сегмент — то очень даже клёво. Разумеется это будет совершенно не так производительно как аналоги, но она далеко не везде нужна.
я тоже не могу прочитать первое слово заголовка без тупой улыбки в стиле
а к чему это тогда? используйте RPC или что вам ближе. Топик всё-же про REST. и выбирая его как протокол взаимодействия всё же стоит придерживаться рекомендаций этого стандарта.
А так да, вас никто не держит за руки. Кто-то пилит псевдо-REST через одни POST запросы, передавая
{type: GET|POST|UPDATE|etc}в теле. Кто-то отдаёт 200 на всё, даже ошибки. Кто-то делает 1 ендпоинт а все параметры переносит в query аляGET: /api/users/:id/books/->/api?model=users&id=:id&field=books. Каждый строчит как он хочетНо когда я начинаю работать над уже существующим проектом, я молюсь чтобы авторы легаси использовали стандарты а не своё "видение". Ибо "видение" очень часто в итоге превращается в боль
согласен. я думаю что мой подход стоит пересмотреть.
но ваш подход вносит гораздо больше неопределённости и излишнего усложнения, по причинам которые я расписал выше.
можно в тело ответа вставлять поле
errorsи при это отдавать правильный статуса можно отдавать ошибку, но "как будто не ошибку" и на клиенте обрабатывать не только успешные и провалившиеся запросы к серверу, а ещё и "немножко успешные, но чуть-чуть провалившиеся"
Кстати нет, на беке проще отдавать всегда 200 и не париться. HTTP коды вводят для улучшения удобства работы с api
так это отлично 400х 500х кодами решается
например на условный
POST: /users/123/im {text: 'hello'}500
{ok: false, message: 'SMTP relay fail: code 1234', trace: ['/path/to','/bla/bla','/lib/smtp',...]}— ошибка кода. когда возник необработанные ексепшнили 500:
{ok: false, message: 'user is not activated yet'}— ошибка бизнесс-логики, когда произошла нештатная ситуация (отправлено сообщение пользователю, но он ещё не активирован)или 404
{ok: false, message: 'user not found'}— ошибка запроса. пользователя с таким ID нету.на клиенте все эти ошибки можно обработать адекватно. а можно и не обрабатывать но знать хотя бы что сообщение не доставлено.
а если мы на 2 и 3 случай будем отдавать 200, то клиент будет думать — а, всё ок сообщение доставлено. он даже не узнает об ошибке, если мы отдельно не пропишем обработку псевдо-успешных запросов
Это я уже запутался. Вы правы, 404 тут как раз и должен возвращаться. Можете 418 попробовать (;
А на практике у меня обычно
404
{ok: false, message: 'not found'}для отсутствия ендпоинтаи 404
{ok: false, result: null}для отсутствия солиэто меня натолкнуло на мысль что стоит подумать над отсутствием соли. вероятно я измению этот ответ в ближайшем будущем.
к слову, для правильного запроса, по которому должен возвращаться массив. например корзина. в случае отсутствия элементов у меня
200
{ok: true, result: []}на клиенте нам важно знать получилось ли выполнить операцию или не получилось. получилось — только для статусов 200
всё остальное (и не важно, пропала сеть, неправльный урл, ошибка сервера, ошибка БЛ, да хоть апокалипсис) — это не получилось, тобишь ошибка.
Вы же предлагаете примешать некоторые ошибки к неошибкам что бы вместо одной проверки удалось/неудалось делать их кучу даже в том коде который должен выполняться когда «удалось».
вы заведомо пытаетесь усложнить код. усложнить состояние приложение. ввести ситуации когда у нас есть не только fail/success а ещё и «какбы success, но немножко fail»
8) забыли про 500х коды. И вообще про коды тут пункт ниочём. список HTTP статусов можно и на википедии посмотреть.
Мой бестпрактис касательно кодов: В самой первой версии апи сделайте поддержку 4х статусов
Этого достаточно на первое время, а если у вас есть бюджет вы всегда сможете расширить этот список. Главное — поддержать хотя бы их.
5) пагинация через link — имхо это даже бэд практис в некоторых случаях. Если мы предоставляем
limit/offset(skip/size и т.п.) — то этого более чем достаточно для пагинации, и создание линков усложняет код, не привнося никакого дополнительного функционала (ведь пагинация и так есть). А вот отказываться отlimit/offsetв пользу линков — плохая идея. мы заведомо ограничиваем возможности клиента, не привнося ничего взамен.7) А что за путаница у него в методах и их индепендности? и счего бы вдруг GET был индепендным? запросив одну и ту же книгу с разницей в несколько секунд, у неё может измениться статус или рейтинг. Но это уже мелочь
Думаю этот спор всё-равно ни к чему не приведёт, но я не вижу тут оверхеда...
В чём конкретно проблема того что ассерты завраплены? С клиентской стороны этого не видно, а для разработки это проще. Не приходится тащить кусок ядра в каждый ассерт в отличае от вашей идеи.
Объект создаётся только потому что с ним работать удобнее. В нём не лежит ни одной функции, и он легко сериализуется в JSON. Все ассерты находятся в прототипе который JS движок не будет пересоздавать на каждый чих.
Да, функциональщина это круто. Но тут получается функциональщина ради функциональщины.
… усложнение кода библиотеки, повышение порога вход, усложнение кода клиента и стоимости его поддержки, без выйгрыша в чём либо.
Теоретически
composeвместе с хитрымcreateComplexRuleмогут дать какой-то прирост в производительности по сравнению сrunAssertAsMethod. Но это уж точно выглядит оверхедом и преждевременной оптимизацией