Что не так с GraphQL?
22 февраля 2023 г.Хотя GraphQL предлагает несколько преимуществ, существуют некоторые потенциальные недостатки и проблемы его использования в C#, которые следует учитывать, прежде чем вы решите его реализовать.
К ним относятся:
Сложность
GraphQL требует нового мышления и реализации API в целом. Это может привести к крутой кривой обучения. Особенно для разработчиков, привыкших работать с REST API.
GraphQL усложняет кодовую базу, усложняя ее обслуживание и отладку. Хотя для C# .NET доступно множество библиотек, они обычно не настолько совершенны и не так хорошо поддерживаются, как библиотеки для других языков программирования.
Кэширование также более сложно с GraphQL, так как каждый запрос потенциально может возвращать разные данные в зависимости от запрошенных полей. Это затрудняет реализацию эффективных стратегий кэширования.
Гибкость GraphQL может усложнить защиту вашего API, особенно если у вас разные правила доступа для ваших сущностей. Вам необходимо убедиться, что пользователи могут получить доступ только к тем данным, которые им разрешено просматривать.
Накладные расходы
GraphQL может увеличить нагрузку на запросы API, так как перед выполнением каждый запрос необходимо проанализировать и проверить. Это оказывает заметное влияние, если сервер получает большое количество запросов или если запросы очень сложные. Может оказаться важным оптимизировать процесс синтаксического анализа и проверки, например, с помощью кэширования или оптимизации плана выполнения запроса.
Другая потенциальная потеря производительности связана с выполнением преобразователей GraphQL. В C# они обычно реализуются с помощью методов, которые возвращают запрошенные данные. Если преобразователи не оптимизированы или требуют дорогостоящих операций, таких как запросы к базе данных, они могут значительно повлиять на общую производительность API. Этого можно избежать, тщательно разработав функции преобразователя и максимально оптимизировав их производительность.
Обнуление
Типы, допускающие значение NULL, являются распространенной проблемой при работе с GraphQL для разработчиков C#. Это связано с тем, что GraphQL по умолчанию не допускает обнуления. На этом основана вся система типов.
Однако в C# допустимость значений NULL — это всего лишь особенность языка, и многие типы и свойства допускают значения NULL по умолчанию. Это вызывает некоторую путаницу при сопоставлении типов C# с типами GraphQL. Чтобы решить эту проблему, вы можете использовать типы, допускающие значение NULL, в своей схеме GraphQL, чтобы указать, что поле может быть пустым.
Например, в вашем классе C# может быть такое свойство:
public string? Name { get; set; }
? указывает, что свойство Name может иметь значение null. Чтобы сопоставить это с типом GraphQL, вам нужно будет использовать класс NonNullGraphType
, чтобы указать, что поле допускает значение NULL.
Например:
Field<StringGraphType>("name", resolve: context => context.Source.Name);
В этом примере StringGraphType
заключен в NonNullGraphType
, что указывает на то, что поле имени может быть пустым. Кроме того, вы можете использовать класс NullableGraphType
, чтобы указать, что поле допускает значение NULL:
Field<NullableGraphType<StringGraphType>>("name", resolve: context => context.Source.Name);
NullableGraphType
заключает в себе StringGraphType
, чтобы указать, что поле имени может быть нулевым.
Используя эти методы, вы можете гарантировать, что ваша схема GraphQL точно отражает допустимость значений NULL для ваших типов и свойств C#.
Пространства имен
GraphQL практически не имеет пространств имен. Это требует, чтобы вы указали полное имя типа, которое включает пространство имен. Если вы не будете осторожны при определении своих типов и полей, вы можете столкнуться с конфликтами имен или трудностями при разрешении правильного пространства имен. Это смешно, но в основном грустно.
Вы можете попытаться избежать проблем с пространством имен в GraphQL C#, вы можете использовать метод ResolveType
, чтобы указать правильный тип для данного объекта GraphQL. Этот метод используется для определения соответствующего типа C# для данного типа GraphQL, что может помочь вам избежать конфликтов имен и проблем с пространством имен.
Вот пример использования метода ResolveType
:
public class MySchema : Schema
{
public MySchema(IDependencyResolver resolver) : base(resolver)
{
Query = resolver.Resolve<MyQuery>();
RegisterType<PersonType>();
RegisterType<CompanyType>();
RegisterType<UnionGraphType>();
}
}
public override Type ResolveType(string typeName)
{
switch (typeName)
{
case "Person":
return typeof(PersonType);
case "Company":
return typeof(CompanyType);
case "Union":
return typeof(UnionGraphType);
default:
throw new ArgumentOutOfRangeException(nameof(typeName), $"Type {typeName} not found.");
}
}
В этом примере метод ResolveType
используется для сопоставления имен типов GraphQL с соответствующими типами C#. Это гарантирует, что для каждого типа используется правильное пространство имен, что позволяет избежать возможных конфликтов имен.
В GraphQL рекомендуется использовать уникальные имена для ваших типов и полей, чтобы избежать любых возможных конфликтов с другими пространствами имен в вашем приложении.
Общие
Обобщения иногда могут создавать проблемы при работе с GraphQL в C#, поскольку GraphQL требует строгой системы типов. В частности, GraphQL не поддерживает открытые универсальные типы.
Одним из решений этой проблемы является использование закрытого универсального типа в вашей схеме GraphQL, где аргументы типа определены явно. Вот пример использования закрытого универсального типа в
public class MySchema : Schema
{
public MySchema(IDependencyResolver resolver) : base(resolver)
{
Query = resolver.Resolve<MyQuery>();
RegisterType<ListGraphType<PersonType>>();
}
}
В этом примере ListGraphType
— это закрытый универсальный тип, представляющий список объектов PersonType
. Аргумент типа PersonType
определен явно, что позволяет GraphQL правильно интерпретировать схему.
Если вам нужно использовать универсальный тип, который может принимать любой аргумент типа, вы можете использовать неуниверсальный интерфейс в качестве типа в вашей схеме GraphQL. Затем вы можете использовать настраиваемый преобразователь для сопоставления интерфейса с соответствующим конкретным типом во время выполнения.
Использование закрытых универсальных типов и пользовательских распознавателей — два распространенных метода работы с универсальными типами в GraphQL C#.
Конец
Многие из этих проблем можно решить при правильном планировании и реализации. При тщательной оптимизации и проектировании можно свести к минимуму эти накладные расходы и добиться производительности API-интерфейсов GraphQL в C#, но это будет стоить вам определенных усилий.
Главное изображение, созданное с помощью Giphy на сайте HackerNoon.
Оригинал