Os sinais de esgotamento das APIs REST
Por Guilherme Forte
Com a API REST é possível solucionar a grande maioria dos problemas de comunicação entre sistemas via WEB. Hoje dificilmente encontramos uma arquitetura onde não existe uma API REST lidando com esse tipo de comunicação. Vemos com muita frequência aplicações onde a conversa entre o back-end e o fron-end acontece utilizando APIs REST. Outro bom exemplo é em uma arquitetura de microsserviços onde em muitos casos eles são APIs REST.
E isso é ótimo. A padronização que as APIs trazem facilitam a vida dos desenvolvedores em muitos sentidos. Porém devemos considerar e estar atentos aos sinais de esgotamento nas APIs REST que podemos cada vez mais encontrar, os terríveis underfetching e overfetching.
Arquitetura
Para fácil compreensão dos desgastes APIs REST, vamos pensar na seguinte arquitetura. Dois aplicativos front-end (um mobile e outro desktop web) que se comunicam com um back-end através de uma API REST. Nesta API temos os seguintes recursos e suas relações: Usuário, Feedback e Mensagem (sendo que os recursos de Feedback e Mensagem são sub recursos do Usuário).
Nesse app, usuários podem mandar mensagens e feedbacks uns para os outros, em uma arquitetura bem básica. Os apps front-end fazem requisições para a API com o objetivo de listar os usuários, suas mensagens e feedbacks. Uma requisição para listar um usuário traz os seguintes dados:
Overfetching
Baseado na arquitetura de exemplo vamos supor que os aplicativos front_end precisam exibir os seguintes dados do cliente: nome, sobrenome e idade. Ao fazermos uma requisição para o endpoint (GET https://appendpoint/users/1) para obter os dados desejados do usuário, percebemos que outros dados também são trafegados e carregados de forma desnecessária, pois não serão usados nessa tela específica.
Isso é um exemplo clássico de overfetching, em que esse tráfego de dados desnecessário pode parecer despreocupante. Porém, em aplicações de larga escala, onde diversas consultas realizam-se a cada segundo, uma queda de performance no sistema pode acontecer, causando travamentos e erros.
Dessa forma, pensando em evitar o overfetching podemos imaginar a criação de um endpoint especificamente para a aquela tela com apenas os dados necessários:
E sim, essa é uma possível solução. Porém ao criar um endpoint específico resolvendo o overfetching dos dados em uma tela, é necessário entendermos que sempre que quisermos evitar o tráfego de dados de forma desnecessária, mais um endpoint específico será adicionado na API REST. Isso pode gerar desorganização, dificuldade de manutenção e redução nos níveis de maturidade da API. A API pode chegar ao ponto de não poder ser reutilizada por um novo aplicativo front-end e até mesmo ter diversos endpoints que retornam dados parecidos. O resultado é muita confusão em seu consumo.
Underfetching
No caso do underfetching vamos imaginar que após obtermos os dados de nosso usuário, devemos exibir todos os amigos desse usuário e seus respectivos atributos. No exemplo, podemos ver que temos todos os endpoints necessários para obtermos essa informação. Porém será necessário fazer uma nova requisição para cada amigo na lista do usuário. Ao fazer isso estamos realizando um underfetching onde a primeira busca traz dados insuficientes. Temos que complementar essa busca realizando diversas outras requisições para endpoints diferentes.
Baseado na arquitetura de exemplo, teremos 4 novas requisições para assim obter todos os dados desejados. Agora supondo que surja a necessidade de que o recurso Usuário passe a ter também uma lista de Feedbacks, como no exemplo:
Com isso, surge a obrigação de mais 4 requisições, aumentando ainda mais o underfetching entre a comunicação dos sistemas.
Para a prevenção do underfetching, pode-se criar endpoints onde o recurso cliente, por exemplo, já traria todos os dados necessários para a tela desejada, junto aos amigos e feedbacks relacionados em apenas uma requisição. Porém dessa forma os problemas já citados na solução do overfetching também poderiam acontecer. Teríamos endpoints extremamente específicos, repetitivos e uma API com um nível de maturidade baixa.
Pensando em performance e analisando o contexto da arquitetura em desenvolvimento, ter uma API REST de baixo nível de maturidade pode não ser uma solução ruim. Evitaremos o underfetching, e existem boas práticas que podem ajudar na organização do código. Porém se estamos falando de uma API em um contexto onde haverá alto consumo dela por diversas aplicações diferentes, o ideal é a utilização de tecnologias diferentes, que possam evitar ambos desgastes citados (overfetching e underfetching), ou garantir que exista uma infraestrutura potente o bastante para conviver com eles.
Os sinais de esgotamento da APIs REST
Os sinais de esgotamento das APIs REST não indicam o fim de sua utilização. Porém, para evitar tráfego excessivo, busca de dados insuficientes na comunicação entre sistemas, lentidão e possíveis travamentos nas aplicações que a consomem, é importante analisar todo o contexto da arquitetura para aplicar medidas que evitem esses problemas.
Pensando em um softwares para uso próprio de uma empresa, com a comunicação apenas entre um front-end e back-end, ter uma API REST de baixo nível de maturidade evitando os esgotamentos pode ser vantajoso. Contudo, para arquiteturas mais complexas, com múltiplas aplicações front-end ou consumidoras de uma mesma API, tecnologias como OData e GraphQL serão mais viáveis. Isso para garantir que redução ou até extinção dos esgotamentos, garantindo uma arquitetura limpa e organizada. Com essas tecnologias, temos um novo respiro no mundo das APIs. E possibilidade de que, no futuro, essas ferramentas estejam presentes e aplicadas na maioria das APIs existentes.
Guilherme Forte é graduado em Gestão da Tecnologia da Informação e especializado em Engenharia de Software. Entusiasta na área de programação, possui mais de 5 anos de experiência profissional e adora aprender novas tecnologias e metodologias de desenvolvimento. No tempo livre, gosta de pegar seu violão e praticar um pouco.