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

Итак, GraphQL — это язык запросов, применяемый Facebook для извлечения данных из графовых СУБД. Язык оказался настолько удачным, что потенциальная сфера его применения значительно шире — его называют «убийцей REST» и даже прикрутили его к реакту в качестве очередного движка управлениями моделями данных. Совсем вкратце о том, что такое GraphQL:

— запрос — это список полей, которые нужно вернуть в ответе. Возвращаются только те поля, которые были запрошены
— поле может оказаться методом с одноименным названием — тогда прямо в запросе указываются параметры этого метода: {name, surname, age, getLikesCount(since: «01.01.2016»)}
— если значение поля или метода — объект, то для него так же надо явно указать список полей: {name, surname, age, bestFriend: {name}}

Есть много разных мнений о том, что именно в нем такое инновационное, но, я думаю, что самая интересная идея вот в чем:

Модель данных — это частный случай модели API


И в самом деле, если в произвольном json заменить поля на методы с пустым списком параметров, то получится какое-то урезанное API:

{
  name: "John",
  age: 25
  friends: [{
    name: "Jenny",
    age: 24
  }]
}

превращается в

interface Human {
  name(): string
  age(): int
  friends: Human[]
}

Этот пример демонструет важное следствие — если API и данные — это одно и то же, то API может возвращать ссылки на другие API, т.е. на объекты, предоставляющие методы, возвращающие данные (или другие API). Важный момент — методы вовсе не обязаны быть идемпотентными, это вполне может быть update/delete или просто вызов некой бизнес-логики.

Ничего не напоминает? Например, граф объектов в работающей программе? С учетом того, что запрос GraphQL, по сути, представляет из себя список методов на корневом объекте, которые нужно вызвать, а также прочих фич:

— строгая типизация
— поддержка интерфейсов
— документированное представление схемы в виде структуры данных

мы получаем, что GraphQL позволяет выставить в сеть произвольный объект! И, в частности, активную доменную модель, самописную или собранную при помощи ORM типа Hibernate

Многим не нравится избыточность GraphQL, его набор фишек и примочек, которыми он оброс за время использования его в фейсбуке. Многие из них имеют смысл только в контексте node.js и конкретного стиля разработки. Но — если у нас есть схема и мы сказали RPC, то очевидное решение — кодогенерация. Если многословные запросы со всем этим `query`, `mutation` и объявлением переменных будут скрыты за API, то этот недостаток нивелируется.

Итого, на выходе получается RPC фреймворк, позволяющий выставить в сеть типизированный, документированный, объектный API, использующий в качестве транспорта json и примитивное (парсер пишется с полплевка) подмножество GraphQL. А также клиентский кодогенератор, предоставляющий удобный интерфейс для вызова.

Осталось его написать :)

Спасибо.
Поделиться с друзьями
-->

Комментарии (24)


  1. Jermes
    28.01.2017 09:33

    его называют «убийцей REST»

    GraphQL — язык запросов. REST — стиль построения архитектуры распределенного приложения. Как мягкое может убить теплое?


    1. Scf
      28.01.2017 09:39

      То, что касается архитектуры, у них более-менее одинаковое. stateless, HTTP, кеширование, унифицированный интерфейс. Отличается представление ресурсов — GraphQL предлагает графовую модель, а REST — иерархическую. Плюс типизация плюс больше гибкости — некоторые вызовы "упаковываются" в модель REST с некоторым трудом. Плюс есть надежда, что GraphQL API получится меньше в размерах, понятнее и проще поддерживаемым. Время покажет.


      1. Jermes
        28.01.2017 12:19

        Это несравниваемые вещи. GraphQL находится в одном ряду с JSON/XML-RPC и SOAP, но не с REST. И ждет его такая же участь.


        1. Carburn
          28.01.2017 12:41
          +1

          REST является альтернативой RPC.


          1. Jermes
            28.01.2017 13:41

            Не является. REST — гораздо больше чем RPC.


            1. rraderio
              29.01.2017 19:00

              Что можно сделать с REST и невозможно с RPC?


              1. Jermes
                29.01.2017 19:56

                REST emphasizes scalability of component interactions, generality of interfaces, independent deployment of components, and intermediary components to reduce interaction latency, enforce security, and encapsulate legacy systems.


                1. rraderio
                  29.01.2017 20:35

                  Т.е. RPC не соответствует ничему из этого списка? Чем REST безопаснее RPC?


                  1. Jermes
                    29.01.2017 22:44
                    +1

                    REST — это подход к построению распределенных приложений или как более точно называют — архитектурный стиль, куда входит набор принципов и ограничений, реализация которых обеспечивает распределенному приложению набор определенных важных свойств таких как: Performance, Scalability, Simplicity, Modifiability, Visibility, Portability, Reliability. RPC — это некое соглашение для вызова удаленного кода и все. RPC можно рассматривать как составную часть REST.


                    1. rraderio
                      30.01.2017 15:33

                      Т.е. RPC не обеспечивает ничего из: Performance, Scalability, Simplicity, Modifiability, Visibility, Portability, Reliabilit", так?


                      1. Jermes
                        30.01.2017 22:03

                        Так. Само по себе RPC ничего не обеспечивает.


                        1. OlegYch_real
                          31.01.2017 10:27

                          сам по себе и REST ничего не обеспечивает
                          особенно когда рестом обзывают любой json over http интерфейс


                          1. Jermes
                            31.01.2017 13:46

                            REST — это набор принципов и ограничений, следование которым обеспечивает вышесказанное.

                            особенно когда рестом обзывают любой json over http интерфейс

                            Какой спрос, когда нечто называют тем, чем оно не является?


                            1. OlegYch_real
                              31.01.2017 16:06

                              REST это набор сказок и их пересказов
                              спроси пять человек что такое REST — получишь десять ответов


                              1. Jermes
                                31.01.2017 16:20

                                Что такое REST написано здесь http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm Спрашивать никого не надо.


                        1. rraderio
                          31.01.2017 10:27

                          А REST обеспечивает? Чем REST обеспечивает Performance?


                          1. oxidmod
                            31.01.2017 13:31

                            Хотябы безпроблемным масштабированием за счет отсутсвия состояния на бекенде (в идеале конечно)


                          1. Jermes
                            31.01.2017 14:05

                            http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm


  1. aol-nnov
    28.01.2017 13:33
    +2

    то API может возвращать ссылки на другие API

    HATEOAS что-ли? :)


  1. Jaromir
    28.01.2017 13:49
    +1

    > парсер пишется с полплевка

    но это не точно


    1. Scf
      28.01.2017 20:43

      170 строк на скале. Рекурсивные парсеры очень легко пишутся при наличии некоторого навыка.


  1. boolive
    28.01.2017 18:52

    Меня название смущает, почему "Graph"? Я от этого ожидаю выборки по графу, с условиями в глубину, ширину и всякое другое. А потом думаю, что это только язык, под который нужно писать парсер на все сложные выборки. С какого момента, может уровня сложности проекта, GraphQL становится оправдан? Начинать проект проще на REST, делая узко заточенное API вместо универсального. Вообще универсальных решений опасаюсь.


    Методы API в возвращаемых объектах — интересная особенность. Какой ценной она реализуется на клиенте и сервере? Легко ли без написанного клиента тестировать такое апи, писать сервер-заглушку?


    1. Scf
      28.01.2017 20:42

      На самом деле все очень просто) На яваскрипте к примеру:


      {
        human: function (name) {
          if (name == "Anna") return {
            name: () => "Anna",
            lastName: () => "Ivanova",
            friends: () => dao.getFriends(name)
          };
          return null
        }
      }

      И вот такой запрос:
      human("anna") { name, friends } вернет
      {human: {name: "Anna", friends: [...]}}


      Логика выполнения запроса вот такая:


      • на корневом объекте вызвать метод humans с параметром Anna
      • на получившемся объекте вызвать методы name() и friends()
      • результат сложить во вложенную мапу по принципу имя_функции: значение

      Итог — мы только что одной короткой строчкой дернули два серверных API.


      1. taujavarob
        31.01.2017 16:00

        Супер. Круто. Понятно и… прогрессивно!

        на корневом объекте вызвать метод humans с параметром Anna

        тогда, наверное:

        humans: function (name) {