Часть 1, Часть 2
Напомним, что в части 1 мы дали немного вводной информации о языке запросов GraphQL, о преимуществах GraphQL API в сравнении с REST API, а также создали корпус схем GraphQL.
На диаграмме типа «ящик с усами» показаны размеры коммерческих и общедоступных схем (цифрами указано количество отдельных типов, которое схемы определяют).
Распределение по сложности схем (количеству определений) среди корпусов схем GitHub, коммерческих и крупных GitHub-схем. Усы показывают минимальные и максимальные значения, а ящики обозначают квартили.Мы заметили, что коммерческие схемы определяют гораздо больше типов, чем общедоступные (по средним значениям 122 против 9). Это натолкнуло на мысль, что некоторые схемы из GitHub-проектов могут быть пустышками. Для проведения сравнений между коммерческими и GitHub-схемами мы выделили внутри корпуса GitHub крупные GitHub схемы, схожие с коммерческими по количеству определений, и получили три подкорпуса схем:
В таблице обобщены данные по размеру схем и функционалу GraphQL, который они задействуют:
Характеристики и функционал корпусов схем.Здесь можно отметить чёткое разграничение между всеми тремя корпусами.
Соглашения об именовании или правила именования помогают разработчикам быстро понимать новые интерфейсы и самим создавать свои собственные — такие же чёткие и понятные. Если сообщество следует соглашениям, от этого все только выигрывают. Посмотрим, какие существуют правила именования GraphQL-схем:
«Официальные» рекомендации
Рекомендованные экспертами GraphQL правила именования изложены в письменных руководствах, а на практике воплощены в схемах-образцах в документации по GraphQL:
camelCase
.Pascal
.Мы проверили эти соглашения в нашем корпусе схемы. В итоге выяснилось, что следуют им далеко не все.
А что на практике?
В следующей таблице показано, как схемы в нашем корпусе соблюдают соглашения об именовании. Кроме рекомендованных правил (верхняя часть таблицы), мы нашли несколько органичных правил именования, по которым сообщество разработчиков открытого ПО, похоже, пришло к единому мнению (нижняя часть). Например:
Input
.Многие схемы проявляют непоследовательность в соблюдении этих правил. К примеру, соглашения об именовании полей snake_case
последовательно придерживаются менее 1% схем (здесь, очевидно, предпочтение отдаётся рекомендованному правилу верблюжьегоРегистра). Однако snake_case
используют 30% всех имён полей в схемах полного корпуса и около 37% схем в некоммерческом корпусе GitHub не менее чем для одного поля.
В целом в таблице наблюдается чёткое разграничение между коммерческими и общедоступными GitHub-схемами. Похоже, что сообщество разработчиков открытого ПО движется в сторону выработки общего мнения по этим правилам, в то время как авторы коммерческих схем вряд ли будут им следовать.
Объём возвращаемых данных GraphQL может выражаться в количестве объектов, пришедших в ответ на запрос.
В первой части уже упоминалось, что в ответ на запрос GraphQL могут прийти данные экспоненциально большего объёма, чем сам запрос. Давайте разобьём схемы на три категории по объёму сложности ответа в наихудшем случае, исходя из размера потенциального запроса: линейные, полиномиальные и экспоненциальные. Так нам будет легче понять использование примеров по схеме, приведённой ниже.
Теперь подумаем об объёме данных, возвращаемых в ответ на запрос адреса компании IBM. На следующем рисунке мы видим, что запрашивается примитивное значение от одной компании, поэтому в ответе объектов будет не больше, чем в запросе.
Запрос адреса IBM возвращает ответ того же объёма, что и сам запрос.Теперь попробуем выполнить запрос на адрес компании IBM и список её сотрудников вместе со стажёрами (см. следующий рисунок). Предположим, что у каждого из D
сотрудников есть D
стажёров. В таком случае в ответе будет получено O(D^2)
объектов. Запросив списки с вложенными списками, мы получили полиномиальное число объектов.
Теперь обратимся к экспоненциальному поведению. Так как все D
сотрудники работают в IBM, они друг другу коллеги. В следующем запросе на список сотрудников мы получаем D
объектов. Затем мы запрашиваем всех их коллег и получаем D^2
объектов. Когда мы запрашиваем уже коллег этих коллег, то получаем D^3
объектов. Таким образом, на наш запрос на n уровней коллег будет приходить ответ с D^n
объектами, то есть экспоненциальное число относительно объёма запроса.
Будут ли получаемые в ответ на запрос данные полиномиально или экспоненциально большего объёма, чем сам запрос, зависит от того, есть ли в схеме вложенные списки или нет. Разница между полиномиальным и экспоненциальным поведением определяется наличием цикла в графе схемы.
Основываясь на таких представлениях, мы пришли к более формализованному анализу. Наш анализ зависит от структуры схемы:
Наш анализ даёт верхнюю границу объёма возвращаемых данных в наихудшем случае, при этом объём этих данных может быть переоценён из-за двух факторов:
D
сотрудников IBM был только один коллега, объём возвращаемых данных был бы O(D)
, а не пугающий O(D^n)
(как предполагает здесь структура схемы).Какие объёмы возвращаемых данных в наихудшем случае мы получаем
В следующей таблице показано, что в наихудшем случае экспоненциальный объём возвращаемых данных характерен для схем большого размера (более 80% коммерческих и крупных GitHub-схем).
Объём возвращаемых данных в наихудшем случае на основе анализа графа типа, где n обозначает размер запроса, а D — максимальную длину полученных списков.Такой результат не вызывает удивления: GraphQL описывает отношения между типами, и наличие в схеме таких отношений, ведущих к сверхлинейному поведению, кажется естественным. Однако этот результат предполагает, что поставщики GraphQL и сервисов ПО промежуточного слоя должны планировать обработку сверхлинейных запросов.
Как защититься
Документация GraphQL рекомендует разбивку на страницы как защиту от чрезмерно больших объёмов возвращаемых данных: с использованием среза или схемы соединения.
Мы проверили наши схемы на разбивку на страницы:
Следующая таблица показывает, что мы получили:
Мы призываем активнее применять пагинацию.
GraphQL — это технология, важность которой постоянно растёт. Мы дали практическую оценку текущего состояния GraphQL, использовав корпусы с широким функционалом, новую методологию построения схем и новый анализ. Какие главные ответы мы получили на вопросы нашего исследования:
Наша работа открывает дорогу будущим исследованиям в изучении таких тем, как инструменты рефакторинга для поддержки правил именования, сдвоенный анализ схем и запросов для оценки объёма возвращаемых данных в ПО промежуточного уровня (например, ограничение скорости передачи данных), а также управляемое данными проектирование.
Перевод статьи James Davis: An Empirical Study of GraphQL Schemas
Комментарии