Но тут не соглашусь. Ещё в первой части статьи я обратил внимание, что вы категорически не согласны с тем, что GraphQL — это RPC. На мой взгляд — это именно так, а точнее — это RPC-based решение со своим языком запросов. То есть это следующий уровень абстракции в архитектуре. Разумеется, на базе RPC можно построить похожую штуку, чтобы предотвращать underfetching/overfetching. На базе RPC можно построить даже сам REST (но не наоборот).
Мы сейчас делаем более простой вариант — либо пишем отдельный метод, либо даём параметр типа "вернуть сокращённый набор данных", "вернуть полный набор данных". Ну, это упрощенно... Если же прикрутить парсер query да ещё и резолверы, чтобы графовую структуру данных обслуживать... то RPC прерватится в GraphQL :)
Так что GraphQL в холиваре RPC vs REST на самом деле на нашей стороне :)
А вот что плохо — так это отсутствие хорошего фреймворка для nodejs, который реализует JSON-RPC с удобными слоями валидации на базе json-схем, проверки требования аутентификации и т.п. на основе конфигурации методов. Так, чтобы было декларативненько. Зато у REST есть NestJS (хотя и к нему есть прикрутки какие-то для использования JSON-RPC в контроллерах)
В итоге приходится писать свой велосипед. И оупенсорсить его пока рано :)
Круто! Рад видеть, что есть в сообществе понимание того, что REST переоценен и просто популярен.
Но! Очень часто критики начинают именно с того, что бросается в глаза — размазывание данных по HTTP-протоколу. Это не самое главное отличие. И оно как раз позитивно для публичных API именно из-за кэширования.
Но самое главное — этоя идея: существительные (сущности) против глаголов (функций). Вот от этого и надо отталкиваться в разработке. Мне приходилось делать сложный краудсорсинговый проект — от REST там можно было бы кукшкой уехать, а с RPC получилось неплохо. Многие начинают пилить бэк на REST и скатываются в совсем не RESTful, а по сути в RPC со всеми минусами REST. Потом начинают тащить во спасение GraphQL, который по сути RPC+язык запросов.
Наконец, по поводу эндпоинтов — тут могут быть разные подходы. В недавнем проекте я использовал микросервисы и каждый — имеет свой RPC-модуль. При этом вполне можно выбрасывать каждый сервис наружу для фронта на отдельный эндпоинт, а внурь (на шину rabbitmq) — на отдельную очередь. Всё очень удобно.
Всё так. От себя добавлю, что документировать JSON-RPC всё также удобно с помощью JSON Schema. А если пишите на ноде, то перед вызовом метода можете делать схемную валидацию с помощью, например, www.npmjs.com/package/ajv. Как минимум меньше проверок валидности params делать в коде, хотя в ряде случаев их не избежать, декларативной схемой не покрыть всю валидацию.
Ну и наконец, с JSON-RPC чуть меньше удобств по просмотру лога запросов в девтулзе, и я искал расширение, но не нашёл.
Поэтому набросал черновой вариант: habr.com/ru/post/467767
Присоединяйтесь к разработке, там ещё как минимум надо фильтрацию и пакетные запросы.
Ну, это хорошо, спасибо, буду знать.
Действительно, овердохрена способов: developers.google.com/web/tools/chrome-devtools/network/reference#filter
Но это для REST, не для JSON-RPC.
Это могло бы быть достижимым, будь фильтрация регулярниками по телу запроса/ответа. Но этого нет, да и было бы тем ещё извращением.
Network в devtools удобен для REST. Можно фильтровать по эндпоинту, что является фильтацией по сущности и как бы подразумевает фильтрацию по методу. Хотя, не знаю даже, можно ли фильтровать по типу HTTP метода? По коду ошибки? Не пробовал.
Но в любом случае, в JSON-RPC для этого нужно парсить тело запроса и тело ответа. А значит, нужно расширение.
А вот фильтры к нему я планирую докрутить попозже.
Да, разумеется, данные по метке времени и инициализатору запроса есть в HAR, так что можно вытащить и показать.
Меня больше смущает то, что в текущей реализации, расширение ловит данные по факту завершения запроса. Т.е. пока запрос в pending, в Network он уже есть, а в расширении ещё нет.
Но это тоже так или иначе можно попробовать решить.
Ну, ваша правда. Снабдил эту статью скриншотом, тем же что в сторе, но без сжатия.
Однако замечу, что ваш интерес это изображение всё равно не удовлетворит, поскольку объекты там как раз «простые», что в params, что в error.
Как ведёт. Ну, обычно, полноценное дерево. Да, наверное может и обгадиться на слишком большом JSON, ну так и сам фронтенд может точно так же на нём спотыкаться.
Это уже чересчур :) Но в целом, попробовав, я решил остаться на JSON-RPC. Бесконечная иерархия запросов, которую даёт GraphQL, мне не требуется, а валидацию можно сделать на JSON Schema и даже, кажется, более серьёзную, со всеми этими min, max, multipleOf, JSON Pointers. Более того, серверную валидацию на схемах можно утащить на фронт, независимо от того, на чём сделан бэк.
Да-да, я в курсе про DataLoader, в том числе, кажется, и по вашему материалу. Но DataLoader заточен на выборку по id и кэширование его так же. А если мы начнём делать выборки из БД с разными наборами полей, то кэширование нужно выключать. Да и прокинуть доп.переменные (в том числе и graphql-ный info объект, который нужен graphql-list-fields) непросто, потому что DataLoader не даёт передавать документы в .load/.loadMany. И это логично, но неудобно.
В сложных случаях весьма неудобно разбирать поля в graphql-list-fields.
Отличный материал, спасибо! Мои пробы с GraphQL меня озадачили несколько другими вещами. Было бы интересно услышать мнение практика.
Сразу упомяну стек, на котором пробовал: nodejs + mongodb
Проблема N+1. DataLoader, конечно, её решает почти полностью, особенно с кэшированием. Но в целом у меня сложилось впечатление, что GraphQL хорошо подойдет для нормализованной реляционной базы, подменяя собой join-ы (и уменьшая стоимость абстракций с помощью DataLoader). Но вот если в проекте, например, mongodb и документы набиты подколлекциями, возникает необходимость ограничивать выборку по полям. И, если, где-то в API всё-таки надо получить к ним доступ, то нужно делать другой тип в Query, резолвер которого уже не ограничен по полям при выборе из базы (например, не использует проекцию в mongo).
Почему не заложена возможность получить набор запрошенных полей в самом резолвере? Есть способы вынимания их из аргумента info, но те что я видел, не позволяют просто понять, какие поля относятся к какой ветке и какому уровню. Или я проглядел?
Я обратил внимание на GraphQL по нескольким причинам:
нафиг эти статусы, методы и кучу эндпоинтов
возможность собрать несколько запросов в один на фронте
схема и автодокументирование
возможность завернуть в другой транспорт вместо http
Но вот реализация на бэке мне кажется не столько гибкой, как хотелось бы, если я хочу снизить стоимость абстракций.
Должны и наверное так и делают. Но здесь речь о легаси-коде. jQuery UI Touch Punch кажется не развивается, а может быть и не используется уже. В большинстве случаев jQuery я не использую. React, Angular, ванила. Иногда приходится определять нативно.
Вообще, с десктопами, которые имеют сенсорный экран, всегда как-то было не очень. Одно время я сталкивался с тем, что разработчики, определяя их как touch-устройства, поддерживали только touch-события и в результате возникали проблемы с управлением мышью. Особенно это касается drag-and-drop на touchstart/mousedown и touchend/mouseup.
Кстати, гугловцы там же рекомендуют:
It is suggest to use PointerEvent APIs to better support both touch and mouse.
Ну если они могут себе позволить лицензии (очевидно академические) на NI LabVIEW и NI Vision, то почему нет? Для прототипирования, думаю, удобнее. Они сосредотачиваются на алгоритмах AI по управлению игрой, абстрагируясь от специфики языков при вводе/выводе изображения, ШИМ-управлении приводами и т.п. И делают это с помощью визуальных средств. Та что для учебных целей — самое то. Если писали на LabVIEW, то знаете сами.
Подскажите, зачем вообще клиенту делать сертификаты и ключи? Вам нужна двухсторонняя аутентификация? Но ведь пользователь слейва всё равно идентифицируется по паролю. Зачем тогда? На клиенте нужно только через CHANGE MASTER TO установить MASTER_SSL_CA, чтобы клиент мог убедиться, что у сервера корректно подписанный сертификат (а для этого ему нужен корневой). Разве не так?
И да, стоит отметить, что проблема с запароленным ключём приводит к ошибке 'Unable to get private key from'. Об это в статье нет информации, только в комментариях.
Да, я понял. Есть еще один момент — на примере я не уловил, где обработка входных данных? Есть ли вообще? Или состояния используются только для группировки действий? В статьей сказано, что ожидаются результаты каких-то «сервисов», но не совсем понятно — как это происходит.
Но тут не соглашусь. Ещё в первой части статьи я обратил внимание, что вы категорически не согласны с тем, что GraphQL — это RPC. На мой взгляд — это именно так, а точнее — это RPC-based решение со своим языком запросов. То есть это следующий уровень абстракции в архитектуре. Разумеется, на базе RPC можно построить похожую штуку, чтобы предотвращать underfetching/overfetching. На базе RPC можно построить даже сам REST (но не наоборот).
Мы сейчас делаем более простой вариант — либо пишем отдельный метод, либо даём параметр типа "вернуть сокращённый набор данных", "вернуть полный набор данных". Ну, это упрощенно...
Если же прикрутить парсер query да ещё и резолверы, чтобы графовую структуру данных обслуживать... то RPC прерватится в GraphQL :)
Так что GraphQL в холиваре RPC vs REST на самом деле на нашей стороне :)
А вот что плохо — так это отсутствие хорошего фреймворка для nodejs, который реализует JSON-RPC с удобными слоями валидации на базе json-схем, проверки требования аутентификации и т.п. на основе конфигурации методов. Так, чтобы было декларативненько. Зато у REST есть NestJS (хотя и к нему есть прикрутки какие-то для использования JSON-RPC в контроллерах)
В итоге приходится писать свой велосипед. И оупенсорсить его пока рано :)
Круто! Рад видеть, что есть в сообществе понимание того, что REST переоценен и просто популярен.
Но! Очень часто критики начинают именно с того, что бросается в глаза — размазывание данных по HTTP-протоколу. Это не самое главное отличие. И оно как раз позитивно для публичных API именно из-за кэширования.
Но самое главное — этоя идея: существительные (сущности) против глаголов (функций).
Вот от этого и надо отталкиваться в разработке. Мне приходилось делать сложный краудсорсинговый проект — от REST там можно было бы кукшкой уехать, а с RPC получилось неплохо. Многие начинают пилить бэк на REST и скатываются в совсем не RESTful, а по сути в RPC со всеми минусами REST. Потом начинают тащить во спасение GraphQL, который по сути RPC+язык запросов.
Для меня самым серьезным минусом первого использования JSON-RPC был не самый удобный способ контроля запросов. Для REST подходит сетевой лог в devtools брайзера. А для JSON-RPC (особенно если эндпоинт один) — это неудобно. Ничего, решилось самописным экстеншеном (https://chromewebstore.google.com/detail/json-rpc-viewer/hnmcofcmhpllkdkncnofkjdlpieagngg)
Наконец, по поводу эндпоинтов — тут могут быть разные подходы. В недавнем проекте я использовал микросервисы и каждый — имеет свой RPC-модуль. При этом вполне можно выбрасывать каждый сервис наружу для фронта на отдельный эндпоинт, а внурь (на шину rabbitmq) — на отдельную очередь. Всё очень удобно.
Это про первый абзац — тут вы правы, да. Он должен был остаться до ката, но не остался.
Мы же написали.
Подскажите, продажи в РФ ведутся или пока нет? Если второе, то когда ждать?
Интересует именно 11ые, в которых Iris.
Ну и наконец, с JSON-RPC чуть меньше удобств по просмотру лога запросов в девтулзе, и я искал расширение, но не нашёл.
Поэтому набросал черновой вариант: habr.com/ru/post/467767
Присоединяйтесь к разработке, там ещё как минимум надо фильтрацию и пакетные запросы.
Действительно, овердохрена способов:
developers.google.com/web/tools/chrome-devtools/network/reference#filter
Но это для REST, не для JSON-RPC.
Это могло бы быть достижимым, будь фильтрация регулярниками по телу запроса/ответа. Но этого нет, да и было бы тем ещё извращением.
Что и написано в трёх (трёх, карл!) местах: статье, описании на сторе и help-е самого расширения
Возможно, буду смотреть. Я пока ограничился
chrome.devtools.network.onRequestFinished.addListener
, чтобы меньше вмешиваться в процесс работы.Но в любом случае, в JSON-RPC для этого нужно парсить тело запроса и тело ответа. А значит, нужно расширение.
А вот фильтры к нему я планирую докрутить попозже.
Да, разумеется, данные по метке времени и инициализатору запроса есть в HAR, так что можно вытащить и показать.
Меня больше смущает то, что в текущей реализации, расширение ловит данные по факту завершения запроса. Т.е. пока запрос в pending, в Network он уже есть, а в расширении ещё нет.
Но это тоже так или иначе можно попробовать решить.
Однако замечу, что ваш интерес это изображение всё равно не удовлетворит, поскольку объекты там как раз «простые», что в params, что в error.
Но, я не уделил этому много внимания, потому что и не писал свой визуализатор json-дерева, а пользовался пакетом www.npmjs.com/package/json-formatter-js
Его демка у автора: azimi.me/json-formatter-js
Как ведёт. Ну, обычно, полноценное дерево. Да, наверное может и обгадиться на слишком большом JSON, ну так и сам фронтенд может точно так же на нём спотыкаться.
В сложных случаях весьма неудобно разбирать поля в graphql-list-fields.
Отличный материал, спасибо! Мои пробы с GraphQL меня озадачили несколько другими вещами. Было бы интересно услышать мнение практика.
Сразу упомяну стек, на котором пробовал: nodejs + mongodb
Проблема N+1. DataLoader, конечно, её решает почти полностью, особенно с кэшированием. Но в целом у меня сложилось впечатление, что GraphQL хорошо подойдет для нормализованной реляционной базы, подменяя собой join-ы (и уменьшая стоимость абстракций с помощью DataLoader). Но вот если в проекте, например, mongodb и документы набиты подколлекциями, возникает необходимость ограничивать выборку по полям. И, если, где-то в API всё-таки надо получить к ним доступ, то нужно делать другой тип в Query, резолвер которого уже не ограничен по полям при выборе из базы (например, не использует проекцию в mongo).
Почему не заложена возможность получить набор запрошенных полей в самом резолвере? Есть способы вынимания их из аргумента info, но те что я видел, не позволяют просто понять, какие поля относятся к какой ветке и какому уровню. Или я проглядел?
Я обратил внимание на GraphQL по нескольким причинам:
Но вот реализация на бэке мне кажется не столько гибкой, как хотелось бы, если я хочу снизить стоимость абстракций.
Как вариант, городить свою версию на JSON-RPC...
Вообще, с десктопами, которые имеют сенсорный экран, всегда как-то было не очень. Одно время я сталкивался с тем, что разработчики, определяя их как touch-устройства, поддерживали только touch-события и в результате возникали проблемы с управлением мышью. Особенно это касается drag-and-drop на touchstart/mousedown и touchend/mouseup.
Кстати, гугловцы там же рекомендуют:
И да, стоит отметить, что проблема с запароленным ключём приводит к ошибке 'Unable to get private key from'. Об это в статье нет информации, только в комментариях.