Обновить
29
Кунцевич Андрей@titulusdesiderio

JS-dev | IT-specialist

8
Подписчики
Отправить сообщение
почему у меня ощущение что на каждом шаге он удивляется всё больше и больше?

В первую очередь хотелось бы сказать ловите наркомана
А во-вторую: если это пустит JS разработчиков в embeded сегмент — то очень даже клёво. Разумеется это будет совершенно не так производительно как аналоги, но она далеко не везде нужна.

я тоже не могу прочитать первое слово заголовка без тупой улыбки в стиле


если вы понимаете о чём я...
пробовал. и перенял этот подход, когда начал писать сам REST-сервера. ибо это удобно
А сама проблема лежит глубже — 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

так это отлично 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: []}

если ендпоинт отсутствует — нефиг отдавать по нему 404
Я фулстек разработчик, с даже бОльшим опытом во фронте. так что я рассматриваю с двух сторон баррикады.

на клиенте нам важно знать получилось ли выполнить операцию или не получилось. получилось — только для статусов 200
всё остальное (и не важно, пропала сеть, неправльный урл, ошибка сервера, ошибка БЛ, да хоть апокалипсис) — это не получилось, тобишь ошибка.

Вы же предлагаете примешать некоторые ошибки к неошибкам что бы вместо одной проверки удалось/неудалось делать их кучу даже в том коде который должен выполняться когда «удалось».

вы заведомо пытаетесь усложнить код. усложнить состояние приложение. ввести ситуации когда у нас есть не только fail/success а ещё и «какбы success, но немножко fail»
Ошибка бизнесс-логики — это ошибка сервера. То что вы её аккуратно отлавливаете — не значит что она не происходила.
ого. большое спасибо! Ваш комментарий был для меня на порядок полезнее статьи (:
ошибки бизнесс-логики — это 500 ошибки.
нет. ошибки должны быть ошибками

8) забыли про 500х коды. И вообще про коды тут пункт ниочём. список HTTP статусов можно и на википедии посмотреть.
Мой бестпрактис касательно кодов: В самой первой версии апи сделайте поддержку 4х статусов


  • 200 — ок
  • 400 — неправильный запрос
  • 404 — не найдено результатов
  • 500 — внутренняя ошибка сервера
    Этого достаточно на первое время, а если у вас есть бюджет вы всегда сможете расширить этот список. Главное — поддержать хотя бы их.

5) пагинация через link — имхо это даже бэд практис в некоторых случаях. Если мы предоставляем limit/offset (skip/size и т.п.) — то этого более чем достаточно для пагинации, и создание линков усложняет код, не привнося никакого дополнительного функционала (ведь пагинация и так есть). А вот отказываться от limit/offset в пользу линков — плохая идея. мы заведомо ограничиваем возможности клиента, не привнося ничего взамен.


7) А что за путаница у него в методах и их индепендности? и счего бы вдруг GET был индепендным? запросив одну и ту же книгу с разницей в несколько секунд, у неё может измениться статус или рейтинг. Но это уже мелочь

Думаю этот спор всё-равно ни к чему не приведёт, но я не вижу тут оверхеда...


В чём конкретно проблема того что ассерты завраплены? С клиентской стороны этого не видно, а для разработки это проще. Не приходится тащить кусок ядра в каждый ассерт в отличае от вашей идеи.


Объект создаётся только потому что с ним работать удобнее. В нём не лежит ни одной функции, и он легко сериализуется в JSON. Все ассерты находятся в прототипе который JS движок не будет пересоздавать на каждый чих.


Да, функциональщина это круто. Но тут получается функциональщина ради функциональщины.


Кроме этого, если оформить в функциональном стиле, мы получим ...

… усложнение кода библиотеки, повышение порога вход, усложнение кода клиента и стоимости его поддержки, без выйгрыша в чём либо.
Теоретически compose вместе с хитрым createComplexRule могут дать какой-то прирост в производительности по сравнению с runAssertAsMethod. Но это уж точно выглядит оверхедом и преждевременной оптимизацией

можно как-то более развёрнуто?
а чем плох:
const validatePassword = pass => validate(pass)
  .hasLettersLatin()
  .hasNumbers();

validatePassword(password1);
validatePassword(password2);
нет. неожиданный кейс… но впринципе это легко реализуемо уже на клиенте проверкой кол-ва ошибок
validate(string)
   .rule1()
   .rule2()
   .rule3()
   .rule4()
   .errors.length < 2;

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность