5 причин, по которым вам не стоит использовать GraphQL

Перевод статьи Esteban Herrera: 5 reasons you shouldn’t use GraphQL

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

Тем не менее, как и любой другой инструмент, это не серебряная пуля.

В этом посте, я расскажу про пять причин, по которым вы не должны использовать GraphQL как альтернативу архитектуре REST:

  1. REST может делать тоже самое, что и GraphQL.
  2. GraphQL делает некоторые задания более комплексными.
  3. Легче использовать веб-кеш в сочетании с REST чем с GraphQL.
  4. У вас могут быть проблемы с производительностью с GraphQL-запросами.
  5. Способ работы GraphQL схем может быть проблемой.

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

REST может делать большинство из того, что GraphQL умеет

GraphQL — это альтернатива REST для разработки API, не замена.

Главное преимущество GraphQL — это возможность отправлять запрос, указывающий только ту информацию, которая вам нужна, и получать именно ее.

Но вы так же можете добиться этого используя REST, передавая названия нужных вам полей в URL (реализуя парсинг и логику возврата информации самим):

GET /books/1492030716?fields=title,pageCount

И это не тяжело реализовать. Существует много библиотек JSON API для многих языков программирования.

Хотите использовать преимущества использования схем и сильной (статической?) типизации для REST?

Используйте JSON-схемы.

Существует много библиотек, которые тоже реализуют и поддерживают эту спецификацию.

Хотите использовать язык запросов в REST API?

Попробуйте OData.

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

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

Но так же GraphQL может сделать вещи намного более сложнее.

GraphQL сделает некоторые задания более сложнее

Использование GraphQL для маленьких приложений (к примеру тех, которые используют всего несколько полей в одном и тоже же виде, каждый раз) не рекомендуется потому, что оно добавляет сложности из-за таки вещей как:

  • Типы (Types)
  • Запросы (Queries)
  • Мутаторы (Mutators)
  • Резолверы (Resolvers)
  • Компоненты высшего порядка (High-order components)

Что не очень хорошо с точки зрения поддержки.

Но даже если использование GraphQL оправдано, могут возникнуть сложности.

Два примера — обработка ошибок и загрузка файлов.

Используя REST, проверка статуса ответа — это единственный способ узнать, что запрос был успешно выполнен, если была ошибка сервера или если ресурс не был найден.

Но в GraphQL вы получите что-то подобное при возникновении ошибки:

{
"data": null,
"errors": [
{
"message": "Validation error...",
"locations": [
{
"line": 5,
"column": 6
}
]
}
]
}

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

Некоторые библиотеки, как Apollo client, помогают с обработкой ошибок, но не так же легко как в REST API.

Насчет загрузки файлов, эта функция не часть спецификации GraphQL, поэтому реализация зависит от вас. Некоторые варианты:

  • Использовать Base64-кодирование, которое сделает запрос больше и дороже что бы закодировать/декодировать
  • Использовать отдельный сервер/API для этих целей
  • Использовать библиотеки, к примеру appolo-upload-server, которые реализуют GraphQL спецификацию множественного запроса (multipart request).

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

Легче использовать веб кеш с REST чем с GraphQl

Я хочу подчеркнуть веб-часть, кеширование на сетевом уровне, потому что вы, безусловно, можете реализовать кеш на уровне базы данных или на уровне клиента с использованием кеша в памяти Apollo Client.

Но кеш, реализованный на уровне HTTP (например, с обратным прокси), который хранит содержимое запроса, может уменьшить объем трафика на сервер или хранить часто доступную информацию в местоположении, близком к клиенту (например, в сети доставки контента).

Поскольку REST API предоставляет множество конечных точек, вы можете легко настроить сетевой кеш для соответствия определенным шаблонам URL, методам HTTP или определенным ресурсам.

В GraphQL существует только одна конечная точка (в большинстве случаев конечная точка HTTP POST), куда отправляются все запросы. Поскольку каждый запрос может быть разным, сложнее использовать этот тип кеширования.

Один из способов уменьшить объем трафика на веб-сервер — это использование постоянных запросов (persisted queries) с помощью persistgraphql.

Этот инструмент назначает идентификаторы для запросов GraphQL, создавая файл JSON, который отображает запросы и идентификаторы. С этой картой клиент отправляет только идентификатор и параметры запроса на сервер, чтобы он мог просто просмотреть его.

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

Проблемы с производительностью с помощью запросов GraphQL

Будучи языком запросов для API, GraphQL предоставляет клиентам возможность выполнять запросы, чтобы получить именно то, что им нужно.

Но что, если клиент отправляет запрос, запрашивающий много полей и ресурсов? Что-то вроде «дайте мне информацию о пользователях, опубликовавших обзор для всех книг этого автора»:

author(id: '1234') {
id
name
books {
id
title
reviews {
text
date
user {
id
name
}
}
}

Вы можете просто позволить своим пользователям выполнять любой запрос, который они хотят. GraphQL API должен быть тщательно спроектирован, а не помещен поверх REST API или базы данных.

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

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

В API GraphQL есть такие инструменты, как Dataloader, которые позволяют вам выполнять пакетные (batch) и кеширующие вызовы базы данных, но в некоторых случаях даже этого будет недостаточно, и единственным решением будет блокировать запросы, вычисляя максимальную стоимость выполнения или глубину запроса. И любое из этих решений будет зависеть от библиотеки, которую вы используете.

Схемы GraphQL могут быть проблемой

Позволяя вам определять схему, GraphQL дает вам много преимуществ, таких как автоматическая проверка и самоанализ.

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

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

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

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

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

type Query {
request(query: String!): Response
}

type Response {
body: String
}

Это происходит за счет большинства преимуществ GraphQL.

В этих случаях лучше придерживаться REST.

Заключение

GraphQL — мощный инструмент, и есть много причин выбирать GraphQL вместо REST. Но не забудьте выбрать правильный инструмент для правильной работы.

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


Слушайте наш подкаст в iTunes и SoundCloud, читайте нас на Medium, контрибьютьте на GitHub, общайтесь в группе Telegram, следите в Twitter и канале Telegram, рекомендуйте в VK и Facebook.