Comments 47
Понятно, что раскрытие полноценного языка недоверенным клиентам - это гораздо большие проблемы, чем предоставление им ограниченного множества предопределенных команд.
Отдельно полноценный язык не страшен. Скажем, SaaS базы данных предоставляют SQL, такой же или более полноценный язык. Многие ещё расширения на JavaScript или Питоне позволяют. Но там строго определено к каким данным должен быть доступ, к каким нет, и это не зависит от пути по графу. И как брать деньги за запрос известно. А вот описанная смесь полноценного языка и сложной системы авторизации, и сложной системы квот, это действительно катастрофа.
SaaS базы данных предоставляют сами базы данных как сервис, понятно что они отдают SQL.
Но GQL, по сути, возвращает нас во времена двузвенных приложений, только с ухудшенной реализацией, распределенностью под капотом, но и со всеми остальными проблемами этого стиля. Причина, по которой хоть кто-то пользуется gql - не понятна.
Но, можно использовать gql как способ описания отдельных entrypoint. Т.е. на каждую конкретную ручку - своя схема в gql, позволяющая только указывать число полей и с жестким ограничением возможностей поиска и, тем более, мутаций. Этот подход работает, позволяет уйти от кривости RESTful и использовать стандартные протоколы. Но нужна зрелая команда.
Про N+1 я спрашивал ещё в первые годы хайпа. Мне говорили что провайдер магически решает вопросы. Видать не всегда =)
Ой как мне хорошо помнится время когда оно считалось "передовой" технологией, что всем срочно на него надо переходить. Благо тогда костьми лёг, но не дали нашим проектам использовать его.
В то время СДЭК как раз был на graphql (возможно и счас), это те времена когда дважды сливалась его база. Прекрасно помню по слухам конечно же, что немного магии вебреквестов и можно получить было доступ к любой переписке саппорта, к любым заказам и данным любого клиента (телефоны, адреса и т.п.) просто тупо перебирая номера отправления (а с ними сложностей никаких, если знаешь логику назначения).
Лучше поздно чем никогда наконец понять что не всё хайповое одинаково полезно. Хотя о чём это я, мы ведь уже в трёх волнах хайпа от этого и все давно о нём забыли. Как забудут о том что сейчас на пике волны и обмазано фреймворками.
А GraphQL и не перестал считаться передовой технологией.
И ваши аргументы просто глупы и нелепы. Как и ваши выводы.
Единственное, что наконец уже пора понять - нет одной убер технологии, которая решает все вопросы человечество. Есть разные инструменты или подходы, которые лучше в той или иной ситуации, а хороший итоговый результат даёт правильная комбинация инструментов и подходов.
Собственно именно в этом ценность специалиста - уметь разобраться в инструментах и правильно встроить их в работу. Все, кто бездумно бегут за хайпом столь же глупы, как и орущие "нафиг он нам не нужон". Если кто-то забивает микроскопом гвозди, это проблема забивающего и микроскоп хуже от этого не становится.
Так что не вижу причин забывать о GraphQL. Зато вижу необходимость осознать уже некоторым людям, что они имеют пробелы в знаниях и начать эти самые знания подтягивать.
Вы, видимо, считаете себя очень умным, но это определённо не так, если не видите противоречия между следующими отличительными свойствами GQL:
Рекурсивные выборки
Денормализованная выдача
Только полнейший профан мог такое спроектировать. И только бездумные овощи делают вид, будто этой проблемы нет.
В GQL есть и куча других проблем, но эта просто вопиющая, ибо не допустить её было бы проще простого, не обрекая разработчиков на изобретение костылей.
Вы, видимо, считаете себя очень умным, но это определённо не так, если не понимаете, что хороший инструмент в неумелых руках становится абсолютно проблемным.
Если graphql так сильно распространен и применяется, но спроектирован полнейшими профанами, то и применяющие его, получается, безумны, просто сумасшедшие? А может быть все не совсем так и только бездумные овощи не понимают причин, по которым эта альтернатива rest'у стала так популярна. Не обошлось, конечно, без хайпа, но есть и рациональные причины. О чем все эти компании из списка adopters в graphql landscape думают (а там далеко не все перечислены, вероятно), странно все это.
Вот тут в видео по следам этой статьи человек описывает ситуации, в которых считает оправданным применение graphql и я с ним согласен: https://www.youtube.com/watch?v=dNoVg9SOjPk
P.S. Наименование "бездумный овощ" я у вас позаимствовал, как и категоричность в целом, но их применение не одобряю и считаю проблемой! В it есть куча других проблем, но эти просто вопиющие, ибо не допустить их было бы проще простого :) Это грубо, мне кажется.
Забавно, человек использует вторичную риторику, чтобы привести вторичный аргумент, отсылающий к аморфному мнению неопределённого круга лиц, а потом обижается, когда об этой его ментальной несамостоятельности упоминают вслух.
Хотите показать себя умным? Нет ничего проще - обоснуйте грамотность решения неограниченно дублировать данные в денормализованной выдаче по глубокому запросу.
Забавно, что человек свою точку зрения считает более значимой, чем мнение довольно крупного круга лиц.
Хотите показать себя умным - пишите почему они так сделали. Вы же написали, что они полнейшие профаны :) Обычно когда так пишут, получается ровным счетом наоборот. Особенно когда грубят - это же паталогия у вас, неуверенность какая-то, я бы сказал ментальная несостоятельность, согласны? :)
Окей, будем знать, что он ещё передовой.
Можете сказать какой(ие) аргумент(ы) вы считаете глупыми и нелепыми? Я не приводил никаких аргументов, по крайней мере, перечитав раз 5 ещё раз своё первое сообщение, не смог найти их.
Есть факт в том, что многие программисты (особенно те, кто недавно в области) предпочитают поиспользовать ВСЁ новое в текущих проектах. Это не хорошо или плохо, это факт. Хорошо когда они изучают технологию и смотрят 1. её все плюсы и минусы 2. можно ли её применить у нас 3. насколько сильно это поменяет зоопарк текущих технологий и насколько валидно перестать использовать зоопарк перейдя на одну эту технологию (по крайней мере в области технологии). А вот плохо это когда они это делают на работающих проектах. Вот это уже аргумент, можете назвать его глупым и нелепым теперь.
Ценность специалиста с моей т.з. не просто уметь разобраться и встроить в работу увеличив и без того вероятный страшный зоопарк исторически сложившийся от таких же специалистов, а в том чтоб разобраться в технологии и понять стоит ли применять её в проекте. Применить чтоб поднять свой скилл? Ну валидно с точки зрения "специалиста", бессмысленно с точки зрения приложения. И это тоже мой аргумент. Когда приложение это собрная солянка передовых технологий разного времени, потом приходящий новый человек говорит какое же это жуткий треш угар содомия и легаси и что ничего не надо трогать, выгорает через несколько месяцев и уходит, а приложение остаётся.
А я и не забываю о ГКЛ, хотя бы по причинам описанным выше со СДЭКом. И моя позиция (конкретно по тому что вы попытались притянуть за уши прочитав каким-то образом в моём первом сообщении) не в том что "не нужон этот ваш интернет", а в том, что описано тут. И у меня например так же нет супер-знаний о какахах, я видел как они выглядят, я знаю как они пахнут, я не хочу их пробовать на вкус и разбирать биологические составляющие, хотя при этом понимаю, что их через годик прекрасно можно использовать в качестве удобрений.
GraphQL хорош в качестве api gateway, когда в нем нет бизнеслогики и он просто ресолвит запрос на разные сервисы, те же самые rest api.
В таком виде проблема авторизации просто не встает, ибо авторизация происходит на уровне бакенда.
Проблему n+1 у себя мы решили без даталоадеров, просто в редких случаях, где она возможна, ресолвер проверяет предыдущий уровень, есть ли там фильтр по идентификатору, то есть запрашивается одна запись, или список? Если список, то запрос к бакенду для ресолвинга определенного поля не делается вообще, всегда возвращается пустой массив.
Проблема с генерацией миллиона ошибок видимо как-то решена была до меня.
Ну а больше в статье никаких проблем не осталось. Связывание я пропустил, ибо там про бизнес-логику, которой в гейтвее нет.
Обзор написан профаном, который из бека смог в ИБ, но не смог в фуллстек. Вместо тысячи саг и простыни редьюсеров, которые нужны при использовании фастапи - графкуэль на фронте позволяет сделать из коробки внутренний кеш с хранилищем состояний и прозрачные компоненты API. Плюс сквозная автоматизированная кодогенарация в TS на основе схемы с бека - это суперкрутая фича. Плюс подписки с вебсокетами из коробки. То что на REST должны делать 10 аналитиков, 5 бекендеров и 4 фронта - на графкуэль могут сделать 2 фуллстека. Это просто тупо быстрее. Все описанные проблемы с безопасностью на беке - решаемы, и объем и сложность кода для их решения - намного меньше чем поддержка реста и обвязки на него. Аргументы в стиле "на авторизацию нужно вешать глобальную миддлварю", "резолвер словит переполнение на жопошную схему" и "сложна писать много сложного кода на беке, хочу фастапи и чилить", "криво сделанный резолвер позволяет делать мегаджойны и рекурсивный N+1" - это аргументы для бедных. Если бек+ИБ и ты не осиливаешь писать много сложного кода на беке, с последующей оптимизацией и ограничением всевозможных проблем, запросов, отладкой и перепиливанием бекового ядра используемого фреймворка графкуэль - возможно просто именно для тебя это слишком сложно. На самом деле написать много сложного кода на беке для исправления озвученных в обзоре проблем - в разы проще, быстрее и аккуратнее, чем поддерживать рест на фронте. А вообще графкуэль это не про супербезопасность, а про скорость вывода новых фич в продакшен с последующей монетизацией в условиях ограниченного финансирования.
Я никогда не писал на графкуэле и не видел готовых решений - всё таки что делается с N+1 то?
Потому что в рест апи я как бэк знаю, что делать, чтобы не было таких проблем. В случае с графкуэлем меня никто не спрашивает, запрос по факту напишет фронт, а как оно сделает реальный вызов из бд - никто не узнает до реального вызова, и то если профилировать и проверять.
del
Я никогда не писал на графкуэле и не видел готовых решений - всё таки что делается с N+1 то?
В GraphQL от N+1 защищаются точно так же, как и в REST. Просто в публичном API проектируют схему так, что выполнить N+1 невозможно. Иногда, когда очень нужно опубликовать "богатый" API, ограничивают глубину запроса на бекенде (во всяком случае в Java все инструменты для этого есть)
Очень помогает в этом патерн проектирования API Gateway. Во "внутренних" микросервисах можно публиковать всё, что угодно - в том числе возможность выполнить N+1. Тут проблема решается постановкой нормального процесса разработки - Code Review плюс автоматизированное и/или мануальное тестирование. К проектированию "внешнего" API нужно относится вдумчиво и серьёзно. В том числе продумывать защиту от потенциальных DDoS атак.
PS
Я вообще против противопоставления REST и GraphQL. GraphQL - это тот же самый REST, но на стеройдах. И минусы у обеих технологий абсолютно одинаковые. Все проблемы, описанные в этой статье, можно запросто схлопотать и на REST. В том числе и N+1 (если постараться). GraphQL просто гораздо более мощный инструмент, чем REST. Поэтому с помощью него гораздо проще выстрелить себе в коленную чашечку. Но это не значит, что от него надо отказываться. Вы же не отказываетесь от езды на автомобиле только потому, что на нём можно развить большую скорость и разбиться? Вы продолжаете ездить на автомобиле. Просто соблюдаете ПДД и проявляете разумную осторожность.
Я может слишком привык к формату разработки вида "фронт-бэк-субд". GraphQL же в моей голове даёт практически доступ с фронта в субд, что выглядит сразу подозрительно и странно.
При трехзвенке есть проработка данных - какие, кому отдавать, в каком объеме, для каких целей. При использовании GraphQL я не очень представляю - остаются ли эти решения? Или фронт сам решит, что запросить, сам определит необходимый объем и всё? Нужен ли нам фуллстек для такой разработки или разработчик фронта может и не представлять, как там бэк и субд обработают запрос?
GraphQL же в моей голове даёт практически доступ с фронта в субд
Это стандартное заблуждение новичков в GraphQL. И в этом вы, поверьте, не одиноки :)
GraphQL не имеет никакого отношения ни к СУБД ни к SQL. GraphQL - это инструмент, позволяющий осуществлять коммуникацию (синхронную и асинхронную) между двумя сервисами по сети.
По способу реализации (коммуникация поверх HTTP и сериализация в JSON) GraphQL очень похож на REST (почти что копия).
Но идеологически GraphQL ближе к gRPC. И тот и другой инструмент построены в парадигме "API First" (есть схема, формально декларирующая API). Оба работают поверх HTTP. Различаются они только механизмом сериализации данных. У GraphQL это JSON, у gRPC это Google Protobuf. Если сравнивать два эти инструмента, то у каждого есть свои плюсы и минусы. У GraphQL гораздо более богатый синтаксис описания схемы. Плюс GraphQL, в отличии от gRPC, может осуществлять не только синхронную, но и асинхронную коммуникацию. При асинхронной коммуникации с помощью подписок GraphQL чем то похож на брокеры сообщений. У gRPC гораздо более эффективный протокол сериализации - Google Protobuf. Грубо говоря, для злого highload я бы взял gRPC. А для построения сложного API коммуникации двух сервисов взял бы GraphQL.
Эм, а как тогда работают вещи типа того что в ссылке ниже - https://graphql.org/conf/2023/sessions/09bc04c42310bfe14024455bce46d781/ описаны? Данные берутся не из БД? А если из БД, то мой вопрос остается актуальным и ответа на него в вашем сообщении я не вижу.
Данные берутся либо из СУБД либо из других микросервисов. В этом GraphQL ничем не отличеется ни от REST ни от gRPC.
Постараюсь выразиться понятнее. С помощью GraphQL нельзя написать и выполнить SQL запрос к реляционной СУБД. Для того, чтобы получить по GraphQL данные из СУБД нужен бекенд, который по вызову GraphQL ендпоинта получит данные из СУБД, преобразует их в JSON, и отправит в качестве ответа по сети. Реализация этого бекенда практически ничем не отличается от реализации бекенда для REST.
Хм, REST не про коммуникацию поверх HTTP и не про сериализацию в JSON. REST - про реализацию гипертекстовых систем на основе идеологии ресурсов и операций с ними.
И в этом смысле GQL никак не связан с RESTом, это совсем другая парадигма, гораздо более близкая к двузвенным архитектурам прошлого тысячелетия и повторяющая все те же ошибки, что были совершены тогда.
И нет, grpc не эффективнее gziped json-over-http на реальных задачах )
Насчёт сравнения GraphQL и gRPC. По-моему разница не в протоколах сериализации, gRPC тот же JSON тоже умеет. Асинхронная коммуникация там тоже есть, см bidirectional streaming. Но в gRPC я описываю методы, возвращающие конкретные данные, известные и описанные заранее для каждого метода. GraphQL это query, где клиент говорит, что и как глубоко он хочет - отчего и возникают всякие проблемы описанные в статье, вроде неожиданных для разработчика N+1, или не планируемого возврата лишних полей. Можно конечно GraphQL использовать как gRPC, по отдельной схеме и реализации на каждый запрос, но зачем, когда есть gRPC?
Еще один способ "защиты" от N+1 - это Dataloader. Но называть это "защитой" не совсем корректно. Это скорее способ уменьшить ущерб от N+1. При грамотном использовании ущерб можно уменьшить до нуля.
Как оно сделает реальный вызов из БД - знает разработчик, реализовавший резолвер на беке. Если бек-разработчик не провел оптимизацию, не оптимизировал запросы и префетчи в более корневом резолвере, который порождает проблему N+1 или просто генерирует супертяжелый запрос - то ему пора пойти и поправить это, правится оно совсем не сложно. Если вдруг по каким то причинам это правится сложно - надо пойти, и поправить фреймворк бекового графкуэля который это не позволяет делать. Вообще, если не использовать автогенераторы схемы БД/фильтров/relay (а их использовать очень удобно), то все резолверы всей иерархии дерева пишутся руками (за исключением листьев - на них резолверы не нужны, т.к. объект-ответ заполняется из резолвера уровнем выше). При такой разработке - у разработчика есть полный контроль над тем, что резолвится ниже по иерархии. Соответственно N+1 можно либо джойнить, либо префетчить, либо ограничть по количеству N, либо закешировать, либо оптимизировать запрос. Как и в обычном ресте. В случае кривого автогенератора - придется форкать фреймворк автогенератора и переделывать его до таких возможностей (что сложно, но вполне реализуемо и существенно легче, чем поддерживать руками на фронте всё то, что делает GraphQL)
Проблему 1 и 2 полностью решает библиотека nestjs-graphql-tools https://github.com/Adrinalin4ik/Nestjs-Graphql-Tools. Что касается авторизации полей это нормально проверять что можно отдавать авторизованному пользователю, а что нет. В ресте этого нет, т.к. концепт другой, однако рест может отдавать много лишнего и отсутствует гибкость (в этом его минус), особенно чувствуется, когда тебе от юзера надо одно имя, а ты тянешь его полностью, либо городишь специальный путь на запрос пары полей из модели. Это же можно отнести к большому бойлерплейту. С кешированием есть проблемы, однако это не везде применимо, а где применимо они либо частично, либо полностью решены. Эффективность graphql точно не ниже чем рест. Любой запрос можно решить по разному. Если у тебя жирная кверя и супер глубокая вложенность, то никто не запрещает тебе сделать сделать специальный резолвер, который соберёт все и вернёт структурированные данные, грубо говоря рест в graphql. Парсинг перед исполнением дело страшное, согласен. Запрос на интроспекцию весьма тяжёлый. С тем же парсингом, он не должен парсить до конца, он должен парсить до лимитов, и это то, что он делает. Если пугает, то сделай лимит на вложенность 2-5 и он глубже не полезет, а сразу выкинет ошибку. При нахождении левой директивы в запросе или дубликата, можно тоже сразу выкидывать ошибку.
Протобаф вместо 1000 графкуклей
Если из ружья выстрелить себе прямо в коленную чашечку - то прострелишь себе коленную чашечку (здравствуй, Капитан Очевидность). Это не повод отказываться от ружья. Это повод не стрелять себе в коленную чашечку - вот и всё.
Все проблемы, описанные в статье - это проблемы безграмотного и бездарного проектирования API (или скорее проблемы отсутствия этапа проектирования API - еще раз здравствуй Капитан Очевидность). На REST при желании можно получить абсолютно те же самые проблемы.
Статья очень тяжело читается, как будто просто перевод американской статьи. Всё ждал когда автор негативным опытом поделится, а получилась телега "если бы, да кабы".
Согласен с автором. GraphQL актуален для задач, когда есть очень «толстое» api с сотнями полей в запросе, и клиенту нужна небольшая их часть. Но это редкий кейс, как правило больших компаний, аля Facebook.
В остальных случаях не очень понятно, какие есть от него плюсы, когда есть кодогенерация REST клиента с типами на основе OpenAPI схемы, которая тоже генерится на основе сервера, а так же есть OpenAPI Editor для ручных запросов.
Советую все-таки почитать про REST, хотя бы диссертацию Филдинга, где вводится это понятие.
И нет, REST никогда не отражение СУБД, он ни в коем случае не должен быть таковым.
Ну и в реальности мало кто использует REST, чаще реально используется какой-то RPC с json-over-http, впрочем, это и правильно. Но там не будет никакого отражения СУБД )
Да, конечно, читал и конечно в оригинале.
Нет, ресурс - это не запись в БД и не кортеж, это то, что может быть уникально идентифицировано. Иногда это несколько записей в БД (агрегат), иногда вообще не про БД, иногда это может быть отчетом (который не запись в БД, но вполне может идентифицироваться uri) или командой в процессе исполнения или много чем еще.
Мне не очень интересно рассматривать REST, он так же мало применим к реализации API (что, кстати, у Филдинга прямо написано), как и GQL. Тем более не интересно обсуждать какие-то фантазии на тему REST.
Почему я отказался от GraphQL