DEV Community

loading...
Cover image for Entendendo o que é GraphQL através de exemplos
Codecasts

Entendendo o que é GraphQL através de exemplos

Vinicius Reis
Married and father a beautiful daughter. I like movies, books, manga, comics, games... That is, I like more things than I have time to do them. I record videos for CodeCasts
Originally published at blog.codecasts.com.br ・8 min read

Mesmo com a popularidade do GraphQL, dúvidas sobre o que ele é, e o que resolve são comuns. Neste artigo pretendo explicar a partir de exemplos o que é GraphQL e qual o seu objetivo.


O que não é GraphQL?

Talvez este não seja o tópico que você esperava encontrar, e algumas das coisas aqui pareçam absurdas, mas acredite há pessoas que pensam ou já pensaram isso sobre GraphQL.

Publicado originalmente em 10/03/2019

GraphQL não é um banco de dados

GraphQL não tem nenhuma relação com o banco de dados, e não é um ORM. Ele nem precisa de um banco de dados para funcionar.
Talvez essa associação exista quando se ouve que ele é uma Query Language.

GraphQL não é um framework

Não se trata de mais um framework, em sua essência GraphQL é uma especificação que possui implementações em diversas linguagens.

GraphQL não é exclusivo para HTTP/APIs

GraphQL não é simplesmente uma nova forma de se criar APIs com HTTP.

Na verdade ele nem usa verbos HTTP, ele desconhece completamente esta camada. GraphQL não se limita ao contexto de aplicações HTTP.


O que é GraphQL?

‘Uma Query Language.’

Infelizmente é uma resposta simples e pouco objetiva. Mesmo que GraphQL em si seja algo simples, por vários motivos a explicação do que ele é não é a mais simples.

O objetivo deste artigo não é entrar nas nuances mais técnicas, porém é necessário explicar alguns conceitos chave.

Tipos e Schema

GraphQL é estaticamente tipado, tudo nele precisa de um tipo associado, e esses tipos formam um schema.

É a partir desse schema que as queries são executadas e consequentemente validadas, tanto entrada quanto saída.

Há alguns tipos base, como String, Int, Float, ID e Boolean. Eles são conhecidos como Scalar Types, e é possível criar os seus próprios tipos, escalares e objetos.

Segue o exemplo da criação de dois tipos, User e Address

Os tipos acompanhados de ! informam que não aceitam null como valor.

O mais interessante deste exemplo é o field address de User, ele aponta para outro tipo, o Address. Podemos assumir que há um relacionamento entre User e Address.

Como esse relacionamento é feito? Não importa, GraphQL não entrega detalhes de implementação, o field address, pode vir de qualquer lugar seja, outro banco, arquivo ou API.

Para que consultas sejam feitas, há um tipo especial no schema, ele é a “porta de entrada”

Aqui temos uma idéia mais completa e elaborada. Em schema informamos que o tipo Query é responsável pela “entrada” das queries, este tipo também costuma ser conhecido como RootQuery.

Em Query temos dois fields, Users e User. Podemos ver também o uso de argumentos em fields, significa que para consumir aquele dado, é necessário passar esses argumentos caso eles sejam obrigatórias.

Apenas User tem uuid com argumento obrigatório, em Users, pagination e search não são obrigatórios.

Neste exemplo de query o recurso User é consumido, passando como argumento uuid. Com base na assinatura do field, se um tipo User não for retornado, o GraphQL informará erro.

Ainda no exemplo antes desse, em Users, o argumento pagination recebe também um tipo como argumento, e como resposta não temos uma lista de User, e sim outro tipo UsersResource.

GraphQL não tem recursos de paginação ou qualquer coisa do gênero, isso deve ser feito através do design do schema que está sendo criado. Este é um dos design possíveis para esse tipo de situação.

Resolvers

A partir daqui o artigo passa a focar na implementação em JavaScript do GraphQL, mas os conceitos são compartilhados entre as outras implementações.

Resolvers são funções responsáveis por, como o nome sugere, revolver um pedido e devolver o dado solicitado. Abaixo segue o exemplo de um possível resolver para Query.User.

É uma função extremamente simples, ela recebe três argumentos: _root_, _args_ e _context_.

Como é um resolver raiz, root não tem valor. Mais sobre ele em seguida.

O segundo parâmetro (args) contém um objeto com o que foi passado para o field quando a query foi feita, no exemplo em questão, um objeto com a propriedade uuid.

O terceiro parâmetro (context) é controlado pela nossa instância do GraphQL, todos os resolvers recebem o mesmo context. Ele é extremamente útil para compartilhar coisas como usuário atual, serviços e coisas como conexão com o banco de dados.

Neste exemplo o uuid de args é utilizado em conjunto do knex de context, e com isso um registro é recuperado do banco de dados.

O retorno de um resolver é uma promessa, o GraphQL espera a resolução dessas promessas para devolver os resultados obtidos. No exemplo acima, se o resultado não for satisfatório o GraphQL informa que houve um erro. Porém, é possível gerar erros mais assertivos.

Agora um erro mais preciso será recebido por quem executou essa query.

Relacionamentos

Como visto anteriormente, é possível estabelecer um relacionamento entre tipos no GraphQL. Foi estabelecido um relacionamento entre User e Address.

Temos duas formas de chegar até o tipo User, através de Query.Userou Query.Users.records. O primeiro devolve apenas um User, o outro uma lista de User, cada um com seu respectivo resolver. Isso só tem importância para se entender que é necessário criar apenas um resolver para o field address.

Este é o resolver User.address. Não importa de onde o tipo User foi recuperado, há apenas um resolver para address. Isso significa que uma vez que isso seja mapeado, todo o seu schema tira proveito disso.

Em userAddressResolver root é o User em questão, dele é extraído a propriedade zipcode. Em seguida zipcode é passado como argumento para zipcodeService . Os detalhes de implementação dele não importam, porém é possivel imaginar que este serviço se comunique com uma API externa que devolve informações baseadas no zipcode.

Vamos acrescentar mais alguns tipos ao nosso schema.

Agora há o tipo Photo e um novo field em Query, o featuredPhotos.

Repare no field url, ele devolve o tipo Url, este não é um tipo nativo do GraphQL, foi colocado apenas como exemplo que é possível criar tipos como esse.

Uma vez que Photo tenha um relacionamento com User, é possível fazer a seguinte query:

Visão geral

Ao adotar GraphQL em sua aplicação, você terá inicialmente uma curva levemente mais lenta no começo, porém rapidamente o valor agregado do GraphQL se destaca, o desenvolvimento do back-end e do front-end se torna mais ágil e dinâmico, menos idas e voltas.

A maior dificuldade do GraphQL não está em sua implementação e uso, e sim no design dele. Ele não tem os problemas de design que uma aplicação Rest possui, porém trás novos desafios.

Ainda não há um consenso difundido sobre padrões de design com GraphQL, mas há uma grande fonte de exemplos e cases.

Pessoalmente acredito na qualidade e versatilidade do GraphQL frente a soluções Rest. Não me sinto mais confortável em criar uma aplicação que não possua o GraphQL como API.

Entre os muitos usos do GraphQL é utilizado como front-end de outros back-end, isso é conhecido como Backend-For-Frontend. Imagine a complexidade de um front-end ter que acessar várias APIs distintas para conseguir uma informação, GraphQL atende muito bem a esses cenários.

E o Rest?

É possível argumentar que com a ajuda de um ORM + algum padrão mirabolante de requests, é possível se obter estes resultados sem o uso do GraphQL

Abaixo alguns destaques que reforçam a adoção do GraphQL

Existe padrão

Na grande maioria dos casos você ou sua equipe iriam inventar algum padrão/método ou aplicar alguma biblioteca para emular esse comportamento (respostas personalizadas, relacionamentos…)

Porém há uma equipe grande e séria por trás da especificação do GraphQL, este artigo não cobre metade das possibilidades.

Auto-documentação

Enquanto seria necessário aplicar ferramentas que geram documentações compatíveis com swagger e similares, GraphQL possui documentação automática, além de um ambiente de testes muito produtivo.

Auto-validação

O sistema de tipos do GraphQL já funciona como um processo de validação, tanto de entrada quanto de saída. Também existe a possibilidade de integração com editores de código que validam as queries da aplicação, além de linhas de comando que podem ser integradas em processos de CI/CD

Realtime

A especificação do GraphQL já prevê real-time. Não são todas as implementações que são compatíveis, porém ela existe e não é complexa.

Isso abre muitas possibilidades antes inexistentes para alguns projetos ou equipes.

facebook/graphql

Iniciando com GraphQL

Este artigo não demonstra como começar com GraphQL, por isso, abaixo está uma lista de recursos úteis para se começar com GraphQL.

Lembrando que GraphQL é implementado em várias linguagens, então escolha a que for mais amigável para você e comece seus experimentos.






Interessado em aprender mais sobre GraphQL? Entre no nosso grupo no Telegram https://t.me/GraphQLBrasil


Não deixe de compartilhar e comentar este artigo. Deixe nos comentários sua opinião sobre esse assunto, pontos que você concorda ou discorda. Vamos agregar mais conhecimento!


Se quiser saber mais sobre meu trabalho visite blog.codecasts.com.br. Assine nosso canal no YouTube, lá você vai ver vídeos sobre JavaScript, jQuery, Gulp, ES6, Vue.JS e muito mais. Também não deixe de entrar em contato pelo nosso grupo no Telegram

that’s all folks

Discussion (1)

Collapse
olimpioadolfo profile image
Olimpio

Muito massa mano... Artigo bem útil e compreensível