6. С GraphQL проще писать код внешнего интерфейса

1. API-интерфейсы GraphQL управляются клиентом

GraphQL имеет архитектуру, управляемую клиентом, а REST — архитектуру, управляемую сервером. Это означает, что GraphQL легче использовать с клиентом.

Если вы хотите получить техническую информацию, GraphQL — это язык запросов, а REST(ful) API — это архитектурное руководство для создания API.

Архитектура, управляемая клиентом, строится в соответствии с потребностями клиента, а API-интерфейсы REST строятся на основе того, что работает на сервере.

Вы когда-нибудь видели архитектурную схему REST API? Обычно они сосредоточены на том, как построена базовая база данных.

Например, REST API может поддерживать операции «CRUD» (создание-чтение-обновление-удаление) для Users, но GraphQL позволяет вам «запрашивать» и «мутировать» их.

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

Но REST API будет серверным, то есть основанным на том, как хранятся данные. Вы «прочитаете» или «обновите» весь объект User.

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

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

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

2. API REST организованы по конечной точке

Помните, как мы только что рассмотрели операции CRUD для REST API? Вам понадобится «конечная точка» (обычно URL-адрес) для каждой операции CRUD.

Разница в том, что в то время как REST использует конечные точки, GraphQL организован в виде систем схем и типов. В конце концов, GraphQL — это язык запросов.

И REST API, и GraphQL API для User могут использовать одну и ту же схему объектов и иметь одни и те же типы, но они в первую очередь относятся к GraphQL.

В конце концов, если вы не настроите конечную точку REST API для клиента на CRUD (создание, чтение, обновление и удаление), они не смогут этого сделать.

Однако предполагается, что вам нужно будет читать («запрашивать») GraphQL, и технически возможно иметь только один URL-адрес GraphQL для всего.

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

Вы указываете допустимые мутации как часть своей схемы, а типы объектов потребуются как часть вашей схемы GraphQL. Это GraphQL.

3. GraphQL подписывается на запросы и мутации

Операции в GraphQL обрабатываются с точки зрения сервера, который прослушивает (или «подписывается») запросы и мутации, в то время как REST использует CRUD.

Обычная микросервисная архитектура для REST (или RESTful) API заключается в создании отдельной Lambda (бессерверной функции) для ответа на запрос.

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



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

С GraphQL вы можете настроить один сервер для прослушивания всего через непрерывный процесс «подписки».

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

Эта модель подписки похожа на то, как работают сервис-воркеры. Например, возьмем Push API, который позволяет отправлять push-уведомления:

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

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

Чтобы приложение могло получать push-сообщения, в нем должен быть активный сервис-воркер. Когда сервис-воркер активен, он может подписаться на push-уведомления, используя PushManager.subscribe()». — Документы MDN

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

Иногда конечные точки REST API бездействуют, поскольку случайный запрос может касаться только каждой бессерверной функции.

4. GraphQL возвращает только то, что вы просите

Вы слышали известную критику объектно-ориентированного программирования, что вы получаете «обезьяну, держащую банан», когда вам просто нужен банан?

Что ж, GraphQL пытается решить эту проблему. Вы не получаете «обезьяну», когда запрашиваете «банан»; вы получите банан, который вы просили.

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

Мало того, что вы можете получить «слишком много» данных из REST API, вы также можете получить недостаточно данных. Чтение Users и Projects требует нескольких вызовов API.

GraphQL имеет здесь большое преимущество, если ваши данные очень сложны. Например, представьте веб-сайт отеля: на нем могут быть мегабайты данных!

Но когда вы находитесь на странице «местоположение», вам, вероятно, не нужна та же информация, что и на главной странице. GraphQL может быть отличным.

С другой стороны, если вы пишете инструмент для поиска в библиотеке, где вам всегда нужно получать всю информацию о каждом Book, REST будет в порядке.

5. GraphQL может быть быстрее, чем REST API

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

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

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

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

Однако, если вам нужно попасть только в одну конечную точку REST, преимущество GraphQL в скорости может исчезнуть.

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

6. Написание внешнего кода проще с GraphQL

С современными инструментами, такими как React Query, обычно очень легко писать запросы и мутации GraphQL.

Помните, как GraphQL имеет клиентскую архитектуру? Кто-то должен был подумать о том, как будет работать фронтенд-клиент.

С другой стороны, разработка с использованием REST API, как правило, медленнее, поскольку они структурированы в соответствии с формой данных.

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

Когда я использую REST API, мне всегда приходится тратить много времени на изучение различных настроенных конечных точек.

Каждая конечная точка REST будет возвращать разные данные. И эти данные будут основаны на том, что хотел вернуть бэкэнд-инженер, а не на том, что мне было нужно.

Конечно, такие инструменты, как Swagger и OpenAPI, могут значительно упростить мне написание внешнего кода с помощью REST, но обычно я быстрее использую GraphQL.

7. GraphQL сложнее изучить

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

REST обычно немного легче понять. В конце концов, это конечная точка с фиксированным действием. Обычно это операции CRUD, но не всегда.

Многие RESTful API имеют целевые конечные точки, основанные на целях, что означает, что они выполняют определенную функцию.

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

Не имеет смысла оставлять ваш клиент (браузер) висящим до завершения машинного обучения, поэтому ответ REST будет «ОК, началось!»

Эту концепцию довольно легко понять, точно так же, как операции CRUD интуитивно понятны и просты.

С другой стороны, для меня нет ничего интуитивно понятного в понимании доступных «мутаций» или синтаксиса запросов.

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

8. GraphQL самодокументируется из-за типов

Написание GraphQL (как во внешнем, так и во внутреннем интерфейсе) считается «самодокументируемым», поскольку вы должны включать типы.

Для сравнения, запрос GET к REST API может вернуть что угодно, из ничего, в объект JSON (нотация объекта JavaScript) размером 3 МБ или больше.



Поскольку GraphQL требует, чтобы кто-то записывал типы, можно использовать такие инструменты, как GraphQL Codegen, для запроса этих типов с сервера.

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

Но когда вы используете GET, POST, PATCH или другие методы запроса HTML для доступа к конечным точкам RESTful, вы понятия не имеете, к чему возвращаетесь.

Конечно, вы всегда можете использовать JavaScript для возврата ответа и проверки объекта ответа с помощью чего-то вроде JSON.stringify().



Но вы не узнаете, какие именно разрешенные типы этого объекта, если кто-то не написал документацию.

Как я уже упоминал, Swagger и спецификация OpenAPI — это один из подходов, которые инженеры бэкенда использовали в своих командах для поддержки REST API.

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

9. Загрузка файлов проще с REST

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

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

Между тем, довольно легко загружать файлы с помощью вызова POST на конечную точку REST, которая его поддерживает. Так что это преимущество для REST API.

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

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

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

Просто будьте готовы прочитать Спецификацию запроса GraphQL Multipart, в которой объясняется, как загрузка файлов работает в GraphQL.

10. Кэшировать проще с REST API

С самого начала GraphQL поддерживает кэширование на внешнем интерфейсе (например, React Query) и на бэкэнде.

Но автоматическое кэширование — это встроенная функция для каждой серверной технологии REST или RESTful API. Он хорошо поддается кэшированию.

GraphQL — это все о настройке и «получении только того, что вам нужно». Помните обезьяну, держащую банан?

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

С другой стороны, если ваш REST API позволяет вам читать Monkey, вы собираетесь кэшировать банан, бамбук и группу крови обезьяны.

В результате кэширование является более сложным как для внешних, так и для внутренних (GraphQL-сервер) библиотек для GraphQL, чем для REST API.

11. GraphQL менее подвержен ошибкам, чем REST API

Это, вероятно, будет воспринято любыми фанатами RESTful API в аудитории, поэтому я ставлю его последним.

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

Конечно, я разработчик TypeScript, который даже не будет говорить с рекрутерами о работе, использующей JavaScript вместо TypeScript, так что YMMV.

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

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

В GraphQL такой проблемы нет, особенно с TypeScript и такими инструментами, как GraphQL Codegen (или стек T3 с tRPC).

Заключение — REST API против GraphQL

Давайте подведем итоги, рассказав о наиболее распространенных случаях использования. Когда вы найдете GraphQL и когда вы найдете REST API?

GraphQL обычно используется с микросервисной архитектурой, мобильными приложениями и сложными веб-приложениями. Вспомните «Ленту новостей Facebook».

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

Для варианта использования RESTful представьте себе чтение Books на книжной полке. Вы будете читать только одну книгу за раз или редко будете открывать две или три вместе.

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

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

Никогда не забывайте обезьяну с бананом. Если вам всегда нужны обезьяна, банан и все остальное, что держит обезьяна, это REST API.

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

И, если вам понравилась эта статья, вам, вероятно, понравится и моя недавняя статья о лучших практиках Git для лучшего программирования:



Удачного кодирования! 🐒🍌

Доктор. Дерек Остин — автор книги Программирование карьеры: как стать успешным программистом с шестизначным доходом за 6 месяцев, которая теперь доступна на Amazon.