Архитектура
АрхитектураИспользование компонентов вместо графов

Использование компонентов вместо графов

Gato GraphQL не использует графы для представления модели данных. Вместо этого он использует компоненты.

Такой подход не является неожиданным. В разделе Thinking in Graphs проект GraphQL утверждает (выделение наше):

Графы — мощный инструмент для моделирования многих реальных явлений, поскольку они напоминают наши естественные мысленные модели и словесные описания лежащих в их основе процессов. С GraphQL вы моделируете свою бизнес-область как граф, определяя схему; внутри схемы вы определяете различные типы узлов и то, как они связаны между собой. На клиенте это создаёт паттерн, аналогичный объектно-ориентированному программированию: типы, ссылающиеся на другие типы. На сервере, поскольку GraphQL определяет лишь интерфейс, вы вольны использовать его с любым бэкендом (новым или устаревшим!).

Главный вывод из этого определения таков:

Хотя ответ имеет форму графа, это не означает, что данные действительно представлены в виде графа при обработке на стороне сервера. Граф — это лишь мысленная модель, а не реальная реализация.

Это хорошая новость, поскольку работать с графами (или деревьями) непросто. Компоненты, напротив, гораздо проще реализовать и при этом предоставляют те же самые преимущества.

Упрощение модели данных с помощью компонентов

Использование компонентов для представления структуры данных на стороне сервера оптимально с точки зрения простоты, поскольку позволяет объединить различные модели данных в единую структуру. Вместо того чтобы иметь такой поток:

построить запрос для передачи компонентам (клиент) => обработать данные как граф/дерево (сервер) => передать данные компонентам (клиент)

...наш поток будет выглядеть следующим образом:

компоненты (клиент) => компоненты (сервер) => компоненты (клиент)

Это достижимо, поскольку GraphQL-запрос можно рассматривать как структуру данных «иерархии компонентов», в которой каждый тип объекта представляет компонент, а каждое реляционное поле, связывающее один тип объекта с другим, представляет компонент, оборачивающий другой компонент.

Рассмотрим пример, чтобы наглядно показать эту связь между компонентом и GraphQL-запросом. Предположим, что мы хотим создать следующий виджет «Избранный режиссёр»:

Виджет «Избранный режиссёр»

Используя Vue или React (или любую другую библиотеку на основе компонентов), мы сначала идентифицируем компоненты. В данном случае у нас будет внешний компонент <FeaturedDirector> (красным), оборачивающий компонент <Film> (синим), который, в свою очередь, оборачивает компонент <Actor> (зелёным):

Идентификация компонентов в виджете

Псевдокод будет выглядеть следующим образом:

<!-- Component: <FeaturedDirector> -->
<div>
  Country: {country}
  {foreach films as film}
    <Film film={film} />
  {/foreach}
</div>
 
<!-- Component: <Film> -->
<div>
  Title: {title}
  Pic: {thumbnail}
  {foreach actors as actor}
    <Actor actor={actor} />
  {/foreach}
</div>
 
<!-- Component: <Actor> -->
<div>
  Name: {name}
  Photo: {avatar}
</div>

Затем мы определяем, какие данные нужны каждому компоненту. Для <FeaturedDirector> нам нужны name, avatar и country. Для <Film>thumbnail и title. А для <Actor>name и avatar:

Определение свойств данных для каждого компонента

И мы формируем GraphQL-запрос для получения необходимых данных:

query {
  featuredDirector {
    name
    country
    avatar
    films {
      title
      thumbnail
      actors {
        name
        avatar
      }
    }
  }
}

Как можно заметить, между приведённой выше иерархией компонентов и этим GraphQL-запросом существует прямая связь.