Эта запись в блоге представляет собой расшифровку моего доклада о GraphQL на конференции GeekCamp.sg. Слайды доступны здесь.

Введение

GraphQL — это новый способ создания и предоставления веб-API.

Сначала мы посмотрим на текущее состояние веб-API. Затем краткое введение в архитектуру REST — именно так сегодня строятся API. Наконец, мы рассмотрим концепции, лежащие в основе GraphQL, и создадим службу GraphQL в Node.js.

Вот ключевая идея моего доклада: пользовательское взаимодействие с API имеет значение. Но сначала немного предыстории современного состояния веб-API.

Веб-API сегодня

Веб-API поглотили мир.

Сегодня у нас есть огромный выбор сторонних API для самых разных нужд: платежи, аналитика, кодирование видео, хранение файлов, транзакционная почта — все больше и больше нашего приложения можно делегировать третьей стороне. Если вы сегодня создаете веб-приложение или мобильное приложение, скорее всего, вы будете использовать веб-API.

Для таких компаний, как Stripe и Sendgrid, чей продукт представляет собой API, очевидно, что пользовательский интерфейс их API имеет значение. Хороший опыт онбординга приводит к большему количеству конверсий и, следовательно, большему доходу.

Но даже если вы не создаете продукт API, на это стоит обратить внимание. Slack — отличный пример.

Многие из нас используют Slack, но что Slack предлагает такого, чего нет в других сервисах обмена сообщениями? Конечно, Skype, HipChat и многие другие службы обмена сообщениями предоставляют ту же самую утилиту?

Это потому, что в Slack есть огромный выбор сторонних интеграций.

Я думаю, что мы можем объяснить часть успеха Slack тем, насколько легко сторонним разработчикам создавать пользовательские интеграции, такие как боты и пользовательские команды, без каких-либо усилий со стороны Slack. Разработчикам Slack не нужно было часами работать над этими функциями, и тем не менее эти интеграции приносят огромную пользу Slack и его пользователям.

Как это возможно? Потому что Slack предлагает отличный пользовательский интерфейс. По мере роста популярности Slack все больше и больше сторонних сервисов будут пытаться оседлать волну.

Обзор ОТДЫХА

Чтобы понять GraphQL, нам сначала нужно понять REST. REST — это текущий отраслевой стандарт для создания веб-API.

Ключевым принципом REST является разделение вашего API на разные ресурсы. Например, платформа для ведения блога может иметь Posts, Users и Comments.

После определения ресурсов мы сопоставляем CRUD действия (например, создание, чтение, обновление, удаление) с комбинацией методов HTTP (например, GET, POST) и URI.

Например, чтобы получить список сообщений, мы делаем HTTP-запрос GET к конечной точке /posts. Чтобы удалить сообщение, мы делаем запрос HTTP DELETE к конечной точке /posts/<post_id>, передавая идентификатор сообщения, которое мы хотим удалить.

Отличительной особенностью REST является то, что вы используете существующие HTTP-методы для реализации значительной функциональности только в одном пространстве имен /posts. Нет никаких соглашений об именах методов (например, /getPosts, /getPostById), а структура URL-адреса чистая и понятная.

В оставшейся части этого выступления давайте представим, что мы создаем клон Hacker News / Reddit.

Какие ресурсы нам нужны?

Пусть будут Posts, Users и Comments.

Вот возможная модель данных для нашего приложения. У нас есть таблица для каждого ресурса, каждая с некоторыми полями.

Мы также предоставляем набор конечных точек REST API для потребителей API, таких как мобильное приложение, для взаимодействия с нашим приложением.

Использование REST API

Далее попробуем использовать наш API.

Вот как выглядит вызов нашего REST API для получения списка сообщений.

Но нам по-прежнему не хватает имени автора, которое не является частью ресурса Post!

Поэтому мы делаем отдельный вызов API для получения пользовательского ресурса…

И сделать еще, и еще…

У нас проблема: несколько циклов обмена. Каждый вызов API для извлечения ресурса представляет собой отдельный цикл HTTP-запрос-ответ. Извлечение сложных графов объектов требует многократных обменов данными между клиентом и сервером, чтобы отобразить даже одно представление.

Для мобильных приложений в переменных условиях сети это крайне нежелательно.

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

Однако это больше похоже на взлом, чем на правильное решение. Мы загрязняем текущее пространство имен ресурсов другим ресурсом.

Еще одна распространенная проблема с RESTful API заключается в том, что мы склонны чрезмерно выбирать данные, которые нам не нужны. Наши API возвращают массивные объекты JSON, хотя мы можем использовать лишь несколько полей.

Решение состоит в том, чтобы позволить клиентам указывать только те поля, которые им нужны. Опять же, это больше похоже на взлом, чем на правильное решение.

Одним из решений проблемы избыточной выборки является создание пользовательских конечных точек, которые возвращают именно те данные, которые нужны каждому клиенту. Это избавляет нас от необходимости вмешиваться в параметры запроса.

Однако такой подход со временем приводит к раздуванию конечных точек. Наши конечные точки также становятся тесно связанными с клиентами.

Еще одна проблема с API — документация.

Кто пользователи нашего API? Если ваш продукт представляет собой API, ваши потребители API — это ваши пользователи. Если вы работаете в среде микросервисов, то разработчики из других команд, которым необходимо использовать ваш сервис, должны изучить ваш API. Или это могут быть новые сотрудники, которым нужно быстро адаптироваться и начать продуктивно работать.

Ваша документация должна отвечать на такие вопросы, как:

  • Какими ресурсами управляет API?
  • Какие действия я могу выполнять?
  • Каковы типы каждого параметра конечной точки?

Лучшее решение, которое у нас есть в настоящее время, — это использование языков спецификации API, таких как Swagger. Написав схему, которая является единственным источником правды о том, что может сделать ваш API, мы можем автоматически генерировать артефакты, такие как документация, серверные заглушки и клиентский код. Это экономит нам массу усилий.

Подводя итог, вот некоторые из недостатков REST, которые GraphQL пытается решить.

ГрафQL

GraphQL состоит из нескольких компонентов: — Язык запросов, позволяющий клиентам описывать форму данных, которые им нужны с сервера. — Система типов, позволяющая клиенту и серверу иметь общий словарь бизнес-домена. — Среда выполнения, которую сервер использует для преобразования клиентских запросов в нужные им данные.

Это независимое хранилище данных — оно не делает предположений о том, какое хранилище данных вы используете. Вы можете использовать SQL, noSQL или даже другой REST API.

GraphQL был разработан для решения некоторых проблем с REST.

С GraphQL вы моделируете свой бизнес-домен в виде графа отношений.

График представляет отношения между различными фрагментами данных, которые у нас есть, и сущностями (например, Book и Author), которые мы пытаемся представить. GraphQL позволяет нам извлекать деревья из этого графа.

Вот пример дерева, которое вы можете извлечь из нашего графика. Сможете ли вы определить другие деревья на этом графике?

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

Язык запросов GraphQL позволяет клиенту описать форму необходимых ему данных.

Формат ответа описывается в запросе и определяется клиентом, а не сервером: они называются запросами, указанными клиентом.

Структура данных не жестко запрограммирована, как в традиционных REST API — использование сервера GraphQL позволяет разработчику на стороне клиента очень легко изменить формат ответа без каких-либо изменений на бэкэнде.

Сервер GraphQL выполняет ту же роль, что и ваш обычный сервер API RESTful или RPC, принимая запросы от клиентов на определенный ресурс в вашем приложении и возвращая ответ. За кулисами служба может общаться с несколькими источниками данных — это абстрагируется от клиентов.

Система типов

Система типов GraphQL позволяет описать схему данных, доступных на сервере.

Язык довольно удобочитаем, но давайте пробежимся по нему, чтобы у нас был общий словарный запас:

  • Post — это тип объекта GraphQL, то есть тип с некоторыми полями. Большинство типов в вашей схеме будут объектными типами.
  • заголовок, автор и комментарии являются полями типа сообщения. Это единственные поля, которые могут появляться в любой части запроса GraphQL, работающего с типом Post.
  • String — это один из встроенных скалярных типов — это типы, которые разрешаются в один скалярный объект и не могут иметь подвыборки в запросе. Мы рассмотрим скалярные типы позже.
  • Нить! означает, что поле не может принимать значения NULL, а это означает, что служба GraphQL обещает всегда давать вам значение при запросе этого поля. На языке типов мы будем обозначать их восклицательным знаком.
  • [Comment] представляет собой массив объектов Comment. Это означает, что вы всегда можете ожидать массив с нулем или более элементов при запросе поля комментариев.

На верхнем уровне каждого сервера GraphQL находится тип, представляющий все возможные точки входа в GraphQL API, его часто называют корневым типом или типом запроса.

GraphQL имеет полноценную систему типов, которая позволяет вам выразительно описать предметную область вашего бизнеса.

Подводя итог, вот как GraphQL решает некоторые недостатки, которые мы видели в REST.

В заключение

Попробуйте GraphQL, особенно если ваш продукт представляет собой API или если у вас много клиентов API с гибкими требованиями.

GraphQL все еще довольно новый, поэтому лучшие практики все еще появляются. Посмотрим, как появится GraphQL.

Первоначально опубликовано на yos.io 2 ноября 2016 г.