GraphQL para iniciantes

Emanuel G de Souza
Training Center
Published in
8 min readOct 1, 2017

Olá pequeno gafanhoto, neste texto farei um introdução ao assunto GraphQL, bem como suas vantagens e um exemplo de uso com o projeto Training Center. Estarei divulgando um boilerplate desenvolvido para Node.js usando o Framework Hapi.js. Espero que você consiga compreender como e porque GraphQL pode ser uma opção interessante para a sua próxima API.

O que é o GraphQL?

E uma query language para APIs. Gosto de pensar no Graphql como uma forma de desenvolver uma API orientado a tipos, pois tudo no Graphql se resume a tipos e resolvers, conceitos que explicarei mais a frente. Uma outra forma de compreender o que é o GraphQL é entendendo que ele é uma abstração ao protocolo HTTP, ou seja, você estará utilizando um endpoint na sua aplicação que estará subindo um server GraphQL nela e este server receberá requests do tipo POST e GET e responderá usando um formato JSON.

O que é interessante é que você poderá subir vários “servers” GraphQL em seu servidor, desde que estejam em diferentes endpoints.

Para entendermos como funciona o GraphQL e sua implementação, vou contar uma história para contexto.

Uma pequena historinha

O pessoal do Training Center se organizou para disponibilizar publicamente e de forma organizada, os pupilos e mentores do projeto, bem como suas características. Assim, contratam a empresa Ordem Jedi para desenvolver a API. A empresa Ordem Jedi é conhecida por desenvolver projetos que são de fácil manutenção, escalabilidade e entendimento. Eles utilizam, para tanto, soluções JavaScript, tanto para servidor quanto para o client.

Como é o Training Center? Bem, o Training Center é um espaço em que pessoas se disponibilizam a ajudar outras a conseguirem dominar skills de desenvolvimento. Este relacionamento ocorre entre o que eles chamam de Pupilo e Mentor. O Pupilo, no início, procura escolher um mentor de acordo com a área de desenvolvimento que ele queira conhecer e dominar, conceito formulado como Carreira. As carreiras disponíveis são: backend, frontend, infraestrutura e fullstack. Taís áreas possuem um corpo de skills que um profissional precisa ter. Cada mentor escolhe uma área para atuar e aceita o pupilo que vai “mentorar”.

Entendendo conceitos

Num primeiro momento, se você fosse modelasse este minimundo, como faria? A primeira coisa é identificar as entidades do sistema: no caso, Pupilo, Mentor e Carreira. A segunda coisa é entender como eles se relacionam. Num segundo momento, iria se questionar quais atributos estas entidades possuem. Vamos enumerar nome, data de nascimento, email para contato, skills e carreira escolhida. Para a entidade carreira, vamos colocar: nome e skills. Cada entidade possui um atributo para a sua identificação, um uuid para ficar melhor.

Se lembra que falei acima de entidade, e mais no início de tipo. Pois bem, tudo em GraphQL é um tipo. O que seria um tipo? Seria uma entidade em seu banco de dados (relacional ou não relacional), poderia ser um Buffer de um dado no servidor de arquivos. As possibilidades são infinitas. Pense em um tipo como um objeto que possui características. Por exemplo, eu poderia ter um tipo Pupilo assim:

O GraphQL possui 2 tipos default: RootQuery e RootMutation. Cada um deles é uma instância mãe de todas daquele tipo. Sendo assim, RootQuery seria a mãe de todas as querys e RootMutation de mutations.

Outro conceito importante é o de resolver. O GraphQL já sabe que você tem um pupilo, mentor e uma carreira. Mas como eu retorno esses caras na minha API? Pelo resolver. Um resolver é uma função que recebe três argumentos: root, argumentos e contexto. Vamos a um exemplo de resolver para o tipo Pupil:

O root em resolver seria o pai daquele resolver no momento da query. What? :)

Vamos a um exemplo, retirado deste link e este link. O GraphQL possui uma árvore de resoluções de query. Ou seja, imagine este arquivo RootQuery e essa chamada ao GraphQL:

Na query executada acima é importante que você tenha a seguinte ideia em mente: root sempre representa o pai na hora da query. Quem seria o root de RootQuery? Ninguém, então o valor é undefined. Mas quem seria o root para o resolver mentor em pupil? Acertou quem disse pupil. O que permite criar o seguinte resolver para mentor e também para carrer, porquê não?

Continuando, o próximo argumento em resolvers é args. Este é simples de entender, são os parâmetros passados na query. Se lembra de RootQuery que mostrei? Então, reparou que tem algumas propriedades que possuem parênteses com uuid dentro? Esses são os args dos resolvers. Para exemplificar, dê uma olhada no pupil.js que mostrei anteriormente. Viu lá que ele recebe em args o uuid?

Para finalizar, falta o contexto. Ah, esse contexto. Acredito que você esteja incomodado de onde vem esse db que uso em todo resolver. Pois bem, esse db é injetado na construção do server GraphQL. Eu posso colocar o que eu quiser que esteja disponível para todos os meus resolvers. Lá vai mais um exemplo de código, mas este de um boilerplate meu.

No primeiro arquivo, eu construo uma rota para a minha aplicação, o /graphql . Esta rota irá ser meu server GraphQL. Reparou que eu passo options? Então, esse cara é um objeto com schema — esquema da minha aplicação — e context, que é o contexto que passo para a minha aplicação. Esse $loadUser é um cara que o Vinicius Reis me apresentou, que é uma forma de assegurar que o usuário esteja autenticado. Isso será importante quando vermos mutations. O mais fenomenal é que se options for uma função, como acima, ela pode receber como argumento, request, pois acaba por se tornar um midleware. Ai eu consigo fazer a magia negra acima.

Em suma, entenda que tudo no GraphQL será um tipo.

Se você especificar um tipo, ele obrigatoriamente precisa aparecer em resolvers. Os resolvers serão as funções que o GraphQL irá usar para buscar o que está no tipo.

Você também pode fazer com que o resolver de um tipo seja um objeto, em que cada propriedade desse objeto / tipo, seja customizada. Isso é interessante quando você tem propriedades que são fruto de relacionamento entre tipos, como no exemplo Pupil X Mentor.

Modificando coisas no seu sistema: conheça as mutations

Você aprendeu até aqui como funciona o sistema de tipos e como trazer dados do nosso sistema para o Training Center. Mas como seria para eu criar um novo mentor? E um novo pupilo? Conheça as mutations.

As mutations são parte integrante de todo e qualquer sistema GraphQL. Porque? Uma coisa que aprendi nas aulas de Projetos Orientados a Objeto com o professor Altemar Sales: todo caso de uso precisa de pelo menos uma query para pegar dados e outra para criar dados. Não seria diferente em nosso sistema.

Como qualquer coisa no Graphql, mutations também são tipos e também possuem uma mãe: RootMutation. As mutations são querys com poderes a mais, sendo assim, todo sistema de tipos que apresentei a você não será diferente aqui. Mas como enviar os dados ao server? Acertou quem disse parâmetro. Eu envio o dado que quero inserir ou atualizar pelo parâmetro na chamada da mutation. E por fim, toda mutation retorna um tipo. Um exemplo de como seria os tipos, query e resolver para criar um novo pupilo nossa API:

A diferença entre a especificação e a implementação

Uma das coisas que me deixaram confuso foi a diferença entre o que é o GraphQL como especificação e a implementação, tanto no servidor como no cliente. A primeira você irá encontrar no graphql.org e no site do Facebook. A segunda já é mais vasto o conteúdo e é o que dá poder de fato ao GraphQL facilitando seu uso e implementação. A principal delas é o GraphQL tools do pessoal do Apollo. Para quem não sabe, o Apollo é uma suíte de ferramentas para o GraphQL com foco em Nodejs e frameworks JS como React, Angular e Vue.js. Portanto, na maioria das vezes você irá encontrar conteúdo sobre GraphQL tools. E sempre tenha em mente essa diferenciação do que seria a spec e a implementação com uma suíte de ferramentas.

TL; TR

Vamos a algumas características principais do GraphQL:

  • Possui uma linguagem muito sucinta e de simples entendimento. Com o seu sistema de tipos, você pode documentar sua api, mostrando quais as entidades ela possui e como estas se relacionam.
  • A resolução dos resolvers é assíncrona, ou seja, se você tiver múltiplos requests no banco de dados, cada um deles será resolvido de maneira assíncrona, todavia, todas elas serão juntadas ao final para formar o resultado, que é a resolução do tipo.
  • Graças a implementação e uso das subscriptions, que não abordarei aqui mas vale uma pesquisa, você pode tornar as coisas realtime.
  • Você tem uma maneira de desenvolver sua api mais amigável, mais maleável.
  • Com as querys você pode trazer exatamente o que quer. Com o sistema de tipos você expõe exatamente o que deve ser exposto.
  • O desenvolvimento de uma tela, seja em um projeto SPA ou não, se torna muito mais simples, pois você pode trazer muito mais informação com uma simples query.

Dificuldades do GraphQL

Como qualquer coisa em computação, GraphQL não é bala de prata. A principal dificuldade que encontrei com o GraphQL é a possibilidade da query explodir com muitas requisições no banco, e o pior, com chaves únicas repetidas. A query e uma máquina de requisição. Como qualquer tipo pode ter outros dentro dele é assim por diante, podemos entrar num loop desses:

Nada que um cache ou DataLoader da vida não resolvam ou amenizam. Na vida real ninguém irá fazer um request desse, mas é possível uma query assim. Aliás, o DataLoader surgiu como uma forma de lidar com essas buscas desnecessárias no banco de dados.

Para finalizar este tópico, gostaria de deixar uma frase que tenho certeza que você conhece

Sabe disso neh? :)

Aonde encontrar mais conteúdo?

Se não sabe por onde começar e como montar sua API, eu tenho um repositório no Github com uma boilerplate de projetos Hapijs + GraphQL. Dá uma olhada lá :)

Bem, é isso galera, mais um texto, agora falando sobre GraphQL. Gostaria de agradecer imensamente ao Vinicius Reis por me apresentar esta tecnologia e me ajudar a compreendê-la. Ao William Oliveira por ter me autorizar a usar o Training Center como exemplo, quem sabe não surge um projeto de API para eles… :). Um abraço galera! Valeu!

Atualização [13–08–2018]

Não posso deixar de mencionar nesse texto, a comunidade de GraphQL do Telegram. Lá é um excelente lugar para se conhecer mais pessoas que usam o GraphQL em seu dia-a-dia, e beber de seu conhecimento e experiência.

Sou Emanuel, Desenvolvedor na decision6 e entusiasta de Inteligência Artificial. Maluco por séries e filmes. Amo programação e tudo que a cerca. Conheça meu trabalho no meu site emanuelgsouza.dev e em meu Github. May the force be with you!

--

--