Что не так с GraphQL?

Что не так с 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.


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE