GraphQL na vida real
Introdução
Primeira mente deixa eu me apresentar. Muito prazer eu sou o Luiz Leite Oliveira, nasci em 1991 na cidade de Belo Horizonte capital de Minas Gerais, meu estado civil é casado, tenho 2 irmãos, atualmente trabalho como desenvolvedor em uma empresa de Belo Horizonte chamada Hotmart, que tem um site hospedado em Hotmart. A Hotmart tem vários produtos como uma plataforma de afiliados construída por micro serviços com back-end, usando tecnologias como Kotlin e Java e front-end em Javascript, uma área de membros com as mesmas tecnologias, e um aplicativo de entrega de conteúdo que tem back-end em Java e o app em Kotlin e Swift. Se você chegou até aqui eu prometo que já to terminando e isso tem um propósito. Para completar eu queria falar que eu amo jogos como Counter Strike em que eu tenho nível Prata 1, jogo também Fortnite tenho 8 guarda chuvas de temporada, e no FIFA já fui top 50K mundial. Como esporte eu pratiquei natação.
Se chegou até aqui vai começar a ficar interessante eu não tinha interesse nenhum que esse post fosse sobre quem sou eu, mas bem provável que nesse primeiro parágrafo alguns ficaram interessados por algumas partes e outras nem tanto. Exemplo: Pode ser que caso você é um back-end de Belo Horizonte se importou mais com a parte que eu citei as tecnologias que são utilizadas em nossos micro serviços. Agora se você é meu irmão você achou muito legal eu citei a minha familia e o resto nesse ponto já nem sabe mais o que eu to falando.
Beleza… legal… e aí?
Tranquilo vamos imaginar que isso tudo fosse separado em micro serviços como seria? Podemos imaginar alguma coisa da seguinte forma:
```mermaid diagram classDiagram Cidade <|– Usuario Cidade <|– Empresa Empresa <|– Usuario Produto <|– Empresa Tecnologia <|– Produto Hobbie <|– Usuario
class Usuario{
+Long id
+String nomeCompleto
+int anoNascimento
+String estadoCivil
+int numeroDeIrmaos
+Cidade cidadeNascimento
+Empresa empresa
+List<Hobbie> hobbies
}
class Cidade { +Long id +String nome +String estado +String pais }
class Empresa{
+Long id
+String nome
+Cidade cidadeSede
+List<Produto> produtos
}
class Tecnologia{ +Long id +String nome +int anoCriacao }
class Produto { +Long id +String nome +List
class Hobbie { +Long id +String nome +String informacaoAdicional }
Agora vamos imaginar que cada quadrado desse por mais absurdo que seja, virou um micro serviço seriam 6 no total, com a ajuda do incrível [Beeceptor](https://beeceptor.com/)
eu criei estes endpoints mockados para responder sobre exatamente o primeiro paragrafo.
### Usuário:
Chamada `https://luizgraphqluser.free.beeceptor.com/users/1` que tem como retorno:
```json
{
"id": "1",
"nomeCompleto": "luiz leite oliveira",
"anoNascimento": 1991,
"estadoCivil": "casado",
"numeroDeIrmaos": 2,
"cidadeNascimento": 1,
"empresa": 1,
"hobbies" : [1,2,3]
}
Hobbie
Chamadas com seus respectivos retornos:
https://luizgraphqluser.free.beeceptor.com/hobbies/1
{
"id": "1",
"nome": "Counter-Strike",
"informacaoAdicional": "Prata 1"
}
https://luizgraphqluser.free.beeceptor.com/hobbies/2
{
"id": "2",
"nome": "Fortnite",
"informacaoAdicional": "8 guarda chuvas"
}
https://luizgraphqluser.free.beeceptor.com/hobbies/3
{
"id": "3",
"nome": "Natação",
"informacaoAdicional": "nada de mais"
}
Empresas
https://luizgraphqluser.free.beeceptor.com/companies/1
{
"id": "1",
"nome": "Hotmart",
"cidadeSede": 1,
"produtos": [1,2,3]
}
Produtos
https://luizgraphqluser.free.beeceptor.com/products/1
{
"id": "1",
"nome": "plataforma de afiliados",
"tecnologias": [1,2,3]
}
https://luizgraphqluser.free.beeceptor.com/products/2
{
"id": "2",
"nome": "area de membros",
"tecnologias": [1,3]
}
https://luizgraphqluser.free.beeceptor.com/products/3
{
"id": "3",
"nome": "app de entrega de conteudo",
"tecnologias": [1,3, 4]
}
Tecnologias
https://luizgraphqluser.free.beeceptor.com/technologies/1
{
"id": "1",
"nome": "Java",
"anoCriacao": 10
}
https://luizgraphqluser.free.beeceptor.com/technologies/2
{
"id": "2",
"nome": "Kotlin",
"anoCriacao": 2013
}
https://luizgraphqluser.free.beeceptor.com/technologies/3
{
"id": "3",
"nome": "Javascript",
"anoCriacao": 2002
}
https://luizgraphqluser.free.beeceptor.com/technologies/4
{
"id": "4",
"nome": "Swift",
"anoCriacao": 2005
}
O problema
Imaginem para o nosso caso quantas chamadas um cliente deve fazer para chegar no nome de todas as tecnologias de para o usuário 1:
Seria uma chamada no endpoint de usuário 1, através dessa eu conseguiria o id da empresa, que me retornaria os ids dos produtos (3 ids), com isso seriam mais 3 chamadas para cada produto e n chamada para cada tecnologia de cada produto. Nosssssss deu para entender que é chamada pra um caramba.
Tá bom esse é um exemplo exagerado mas quantas plaformas já vimos um front exibindo nome do usuário, postagens que esse usuário fez, e informações de trabalho. Se cada um mesmo sendo as vezes 3 chamadas isso multiplicado por quilos de throughput fica bem pesado.
Nesse primeiro caso falamos só de obter os dados (GET) mas imaginem o quão inflexível essas API’s podem ser para o nosso cliente que quer fazer um teste A/B salvando um dado ao mesmo tempo que outro.
Parte da Solução
Em 2012 o Facebook desenvolveu internamente o GraphQL e em 2015 soltou uma release para o público. Essa tecnologia rapidamente ganhou o gosto de muita gente, pois era uma maneira de receber apenas os dados que eram interessantes para você. Entenderam um exemplo? Para aquele caso do inicio você teria que ouvir praticamente toda a “história” para saber quais eram as tecnologias, agora com GraphQL existe a possibilidade de obter apenas aquilo que quer.
No caso um exemplo de chamada para esse exemplo seria algo do tipo:
usuario(id: 1) {
nome,
empresa {
nome,
produto {
tecnologia {
nome
}
}
}
}
Essa chamada retornaria todas as tecnologias utilizadas pelos produtos, da empresa vínculados ao usuário de id = 1
Cuidados ao Utilizar GraphQL
Tratamento de erros
Como GraphQL não segue o padrão Restfull o client pode receber um erro interno 200. Ainda não há um acordo comum de como tratar isso mas boa parte diz que deveriamos ter uma parte no schema para isso.
Não é uma bala de prata
As chamadas internas do GraphQL devem ser tratadas com resolvers não funcionam como mágica, se um dado não for solicitado na chamada podemos não busca-lo e isso vai ajudar muito na sua consulta.
O projeto
Isso tudo que está descrito aqui pode ser encontrado no seguinte repositório além disso eu tenho um outro post explicando melhor a parte do Quarkus e GraphQL sendo aplicado nele.
Quer acompanhar um pouco mais?
Me siga nas plataformas.
GitHub: luizleite-hotmart
Twitter: luizleite_
Twitch: coffee_and_code
Linkedin: luizleiteoliveira
dev.to: luizleite_