Quando usar GraphQL vs REST
O protocolo de comunicação padrão da internet é através dos verbos HTTP, permitindo a troca de dados entre os serviços e aplicações. O estilo arquitetural mais conhecido para essa finalidade é o REST.
Outra arquitetura que permite essa comunicação e troca de dados é conhecida como GraphQL, que iremos tratar neste artigo com mais detalhes.
O que é GraphQL?
GraphQL é uma linguagem de consulta de API, criada pelo Facebook em 2012 e lançada publicamente em 2015, que define especificações de como uma aplicação precisa solicitar os dados do servidor, sem que seja retornado nenhum dado além do requisitado pelo cliente.
Mas antes de começarmos a falar sobre GraphQL, é necessário conhecer algumas definições como Type, Query, Mutation, Subscription e Schema.
Definições importantes para aprender
É importante conhecer as principais definições para um melhor entendimento de como GraphQL funciona. Vamos a eles:
Type
Type é a definição do tipo de dado da linguagem para o nosso domínio de negócio, por exemplo. Imagine Type como um tipo de dado, como o Integer
do Java.
Query
Query é como se fosse uma linguagem de consulta para recuperarmos o dado de uma API, especificando quais recursos e quais dados serão necessários pelo cliente. Imagine como uma API GET, onde apenas retorna os campos solicitados da query, mas não os altera.
Mutation
Mutation é como se fosse uma linguagem para manipulação de dados da API. Imagine Mutation como um POST/PUT/DELETE/PATCH de uma API REST.
Subscription
É uma funcionalidade interessante do GraphQL que permite o cliente se inscrever para receber eventos de atualização de uma Mutation em real-time. Imagine como um sala de chat, onde você recebe todas as mensagens assim que você entra na sala, por exemplo.
Schema
Schema é um documento que define nossa API. Ela define todo os tipos de dados, queries, mutations, subscriptions e tudo que for necessário para recuperação e manipulação dos dados da API. Schema é apenas uma definição sem nenhuma implementação.
Motivações para usar GraphQL
Uma das principais motivações para se utilizar a arquitetura GraphQL é:
- Desempenho de rede: Ideal para quando queremos aumentar o desempenho e melhorar performance de rede e solicitar apenas informações necessárias e relevantes para o cliente.
- Gerenciar diferentes tipos de clientes: Ideal para APIs que são utilizadas por aplicações web, desktop e/ou mobile, onde cada aplicação gerencia e solicita dados do servidor do jeito que desejarem.
- Um ponto de entrada da API: Todas as operações são centralizadas através de um único ponto. Isso permite recuperar diversos recursos com apenas uma chamada da API.
- Fortemente tipada: GraphQL é fortemente tipada, onde cada consulta corresponde a um tipo particular e cada tipo possui vários campos disponíveis. Pode se dizer que é similar ao SQL e disponibiliza validação e mensagens de erro, antes da query ser executada.
E os trade-offs?
Quando adotar uma nova tecnologia, é importante entender quais são as suas limitações, não somente seus benefícios, para uma melhor clareza na decisão e com GraphQL não é diferente.
Considere as seguintes limitações e complexidades ao utilizar GraphQL:
Operações potencialmente lentas
No Schema, são definidos os tipos de dados que o cliente pode consultar, e o GraphQL define como esses tipos serão renderizados na resposta. Dependendo das definições no Schema, essas operações de conversão podem ser executadas lentamente, e até mesmo utilizar recursos excessivos do servidor, afetando a performance.
Por isso é muito importante ter um Schema bem definido e que atenda todas as operações e as necessidades dos clientes da API.
Complexidade na estrutura das Queries
Enquanto a flexibilidade de fazer as queries é uma vantagem, isso também pode gerar queries complexas, principalmente se precisar recuperar recursos relacionados.
Curva de aprendizagem
Fazer a migração ou desenvolver uma nova API usando GraphQL requer uma curva de aprendizagem para os desenvolvedores e para os clientes que irão usar a API. Entender melhor como utilizar as queries, mutations e subscriptions demanda tempo e esforço.
Complexidade no backend
Para implementar GraphQL no backend é mais complexo do que o desenvolvimento de uma API RESTful, além de ser necessário ter dependências adicionais para implementá-la. Uma dependência no cliente também será necessária.
Problemas com Cache
É mais complicado implementar Cache quando se utiliza GraphQL em relação ao utilizar REST. Em GraphQL é complexo, porque cada consulta pode ser diferente, mesmo com operações que recuperem o mesmo recurso.
E quando usar GraphQL vs REST?
Em termos gerais, não deveríamos considerar uma comparação entre GraphQL e REST para identificar qual seria a melhor das suas arquiteturas, mas sim para atender melhor a opção de acordo com seu projeto.
Eu tentei buscar cenários onde é mais indicado a utilização do GraphQL sobre o REST e esse foi alguns dos cenários que achei adequado:
- Você tem largura de banda limitada e deseja reduzir o número de requisições e respostas ao servidor.
- Você possui várias fontes de dados e quer centralizá-las em um único endpoint.
- Você tem solicitações de clientes que mudam significativamente e espera respostas muito diferentes.
Definição e utilização
Para criar um serviço utilizando GraphQL é preciso que sejam criados os tipos de dados(Types) e suas consultas(Queries). Por exemplo, imagine o serviço que recupera o usuário logado da aplicação, que está representado na propriedade me
e a definição do seu tipo seria User
. A definição da nossa query, no Schema, seria algo como:
type findUser {
me: User
}
type User {
id: ID
name: String
}
Nossa definição do Schema é independente de linguagem.
E como seria a implementação no Backend?
Para a nossa implementação, iremos utilizar o framework Spring Boot para criarmos o nosso Controller
, executar nossa query e retornar os dados do usuário logado.
// .. package
// .. imports
@Controller
class UserController {
@QueryMapping
User findUser() { // nome da query
return service.findCurrentUser();
}
}
// tipo de dado que será retornado na resposta
record User(Long id, String name);
Agora vamos dizer que o nosso cliente da API gostaria de recuperar apenas o atributo name
, do tipo de dado User
, nossa query seria conforme abaixo:
query {
findUser {
name
}
}
No caso, a nossa aplicação irá receber a query, validar e executar, garantindo que ela se refira apenas aos tipos de dados e campos definidos no Schema, evitando que sejam executadas queries inválidas. Após a execução, irá produzir a resposta conforme abaixo:
{
"data": {
"findUser": {
"name": "Luke Skywalker"
}
}
}
Caso o cliente queira recuperar todos os atributos de User
, a nossa query ficaria assim:
query {
findUser {
id
name
}
}
Apresentando uma resposta como:
{
"data": {
"findUser": {
"id": 1,
"name": "Luke Skywalker"
}
}
}
Com isso, conseguimos mudar a resposta do servidor, de acordo com sua necessidade, sem ser necessário realizar qualquer alteração no backend.
Conclusão
Nesse artigo exploramos um pouco o universo do GraphQL, desde seus fundamentos até suas aplicações práticas de uma query, por exemplo, e vimos como GraphQL é inovadora na forma como desenvolvedores e APIs interagem, oferecendo uma experiência mais flexível, eficiente e poderosa.
Contudo, é preciso também analisar seus trade-offs e verificar se irá atender as necessidades do seu projeto.
Lembre-se: este artigo é apenas um ponto de partida. Iremos explorar um pouco mais do potencial do GraphQL com exemplos práticos em artigos futuros.
Fique à vontade para compartilhar sua experiência sobre GraphQL e não deixe de visitar o site oficial e o repositório do Github.