Backend Roadmap

Padrões de Projetos para APIs REST?

Padrões de Projetos para APIs REST?

API REST Design Patterns Arquitetura de Software

Backend Roadmap

Padrões de Projetos para APIs REST?
Anatomia do Protocolo HTTP
Backend: O desenvolvedor invisível

Motivação

A motivação desse post é fazer um estudo sobre quais são os Design Patterns e Anti-Patterns para REST APIS. APIs é uma tendência atualmente e como desenvolvedor Backend sempre me preocupei em criar boas, e bem projetas, APIs. Creio que conhecendo tanto os Design Patterns quanto os Anti-Patterns, vou melhorar ainda mais minha capacidade de projetar boas APIs.

Levantamento Bibliografico

Para fazer o levantamento desses Patterns, resolvi buscar na academia, por isso fiz um levantamento usando o Google Scholar e os termos:

Minha intenção é buscar artigos publicado nos últimos 10 anos que me tragam insights para o meu proprio aprendizado.

Os artigos selecionados para leitura foram:

Resumos

Detection of REST Patterns and Antipatterns: A Heuristics-Based Approach

Palma propões uma analise de Patterns e Anti-Patterns baseado nas hueristicas que os proprios Patterns propõe. Esse artigo foi escrito antes da proposição do OpenAPI, em 2015. Na analise foi uma identificação das requisições e respostas, baseada nas implementações de clientes das APIs.

Foi identificada que muitas das APIs comerciais da época implementavam Anti-Patterns e Design Patterns.

Resultados

A Framework for the Structural Analysis of REST APIs

Haupt propões uma analise estrutural baseada na documentação da API usando OpenAPI. A documentação de APIs abertas foram analisadas por uma ferramenta para se extrair o modelo dela. Ele por sua vez se baseia no Atomic Resource Model e no URI Model. O segundo modelo estende o primeiro, dando a oportunidade ao cliente da API de navegar nos recursos baseados em hyperlinks providos pela propria API.

Atomic Resource Model

Com essa analise é possivel conhecer a complexidade da API, descrevendo quandos Recursos ela possui, quantos desses são ReadOnly e quais as relações entre eles através de links.

Defining Design Patterns for IoT APIs

Svensson faz uma analise de algumas APIs de mercado para IoT e propões 8 Design Patterns, baseado no modelo do GoF. APIs de IoT são altamente voltada a recursos, pois cada dispositivo é um recurso. Segundo Svensson, os Patterns presentes na literatura são mais voltados para garantir a qualidade RESTful das APIs e não para o design dos endpoints, por isso todos esses Patterns são voltados para o endpoint.

Anatomia de uma Requisição

Segundo a IETF RFC 3986, uma URI deve ser dividida nos seguintes componentes:

Scheme://Authority/Path?Query#Fragment

Cada componente de uma URI tem sua especificidade e significância que deve ser levada em conta na construção de uma API.

Componente Descrição Exemplo
Scheme Define sobre qual protocolo essa API está sendo disponibilizada. APIs REST são obrigatoriamente disponibilizadas via HTTP, logo para nosso caso teremos apenas HTTP e HTTPS http://www.google.com/
Authority Define onde está a API e como será acessada. Na grande maioria dos casos é composto pelo hostname do serviço, mas este pode ser substituido pelo endereço IP. Pode contar ainda qual autenticação será feita e a porta a ser acessada. https://api.twitter.com/1.1/search/tweets.json
Path Contem dados organizados hieraquircamente através de nós. Cada nó é separado por “/”  
Query Parâmetros opcionais ou obrigatórios da requisição  
Fragment Parâmetros que não serão considerados na requisição  

Svensson subdvide o Path em Base e Main. Base normalmente é usado para definir qual API e/ou qual versão da API deve ser acesada. Enquanto o Main é o ponto crucial da requisição. Dentre os nós de um Path, é possível também classificar sua função.

Scheme://Authority/Base/Main?Query

Nome Descrição
Nó de Acesso Um nó que é usado apenas para direcionar as seguintes partes do URI para uma determinada seção da API, ou seja, não é um recurso ou dados que podem ser buscados.
Nó Pai Um nó que geralmente representa uma categoria, um recurso que inclui recursos ou um objeto. Na API e no URI, esse nó existe em uma hierarquia. Aqui, tendemos a mencionar apenas o fim da hierarquia.
Nó Indicativo Um nó que representa uma ordem, consulta ou ação a ser realizada em um determinado recurso para aplicar esta ação ou conhecer uma informação específica sobre esse recurso, por exemplo, filtrar os resultados de uma solicitação feita em um determinado recurso. Podemos pensar nisso como um ponto final que dispara uma função. Geralmente é uma palavra convencional, como info, ‘create’, ‘last’, ‘status’, etc. Nós indicativos podem ser divididas em três categorias: Nós de Ação, Nós de Filtro e Nós Informacionais
Nós de Ação Um nó usado para acionar uma função específica ou aplicar funcionalidades clássicas de CRUD em um recurso, usando qualquer método de solicitação HTTP. Na maioria dos casos, esses nós assumem a forma de um pedido para realizar uma ação, por exemplo, “create”, “clone”, “upload” ou “consume”
Nós de Filtro Um nó usado para direcionar um grupo específico ou estado dos recursos solicitados.
Nós Informacionais Um nó usado para obter informações sobre metadados para um ou vários recursos. Esses metadados não podem ser modificados diretamente nem acessíveis por meio do recurso

Svensson também classifica a Authority como dinâmica e estática.

Design Patterns

Micro-Level Patterns

Entity Linking

Este padrão permite a comunicação em tempo de execução através de links providos pelo servidor no corpo da resposta ou via Location:, no cabeçalho da responsta. Usando hyperlinks, cliente e servidor, estão fracamente acoplados, e o cliente pode automaticamente encontrar as entidades relacionadas em tempo de execução.

Response Caching

O cacheamento da resposta é uma boa pratica para evitar enviar requisições duplicadas e respostas através do cacheamento de todas as mensagens no local da máquina do cliente. São usados os cabeçalhos Cache-Control e ETag, assim como o código HTTP 304.

Content Negotiation

Esse padrão suporta representações alternativas para recursos, (por exemplo, em json, xml, pdf, etc.) assim o serviço consumidor se torna mais flexivel com alta reutilização. Servidores podem prover recursos em qualquer formato padrão requerido pelos clientes. Este padrão é aplicado através dp HTTP Media Types e adere ao principio de serviço de baixo acoplamento.

End-point Redirection

A funcionalidade de redirecionamento através da Web é suportado por este padrão, que também desempenha um papel importante como meio de composição de serviços. Para redirecionar clientes,o servidor envia uma nova localidade para acompanhar um dos códigos HTTP entre 301, 302, 307 ou 308. O principal beneficio desse padrão é - um serviço alternativo continua ativo mesmo que o endpoint requerido não responda.

Entity Endpoint

Serviços com um único endpoint são pouco granular. Usualmente, um cliente requer ao menos dois identificadores: um global para o serviço em si e um local para o recurso ou entidade gerenciada pelo serviço. Aplicando este padrão, isto é, usando multiplos endpoints, cada entidade (ou recurso) de um serviço incorporado pode ter seu identicador único e endereço global.

Anti-Patterns

Breaking Self-descriptiveness

Desenvolvedores de APIs REST tendem a ignorar os cabeçalhos padrão, formatos e protocolos e criam customizações proprias. Esta pratica quebra o carater auto-descritivo e a mensagem contida no cabeçalho. A ausência do carater auto-descritivo limita a reutilização e a adaptabilidade do recurso REST.

Forgetting Hypermedia

A falta de hipermídia, ou seja, a não vinculação de recursos, dificulta a transição de estado para aplicativos REST. Uma possível indicação deste antipadrão é a ausência de links de URL na representação de origem, o que normalmente restringe os clientes a seguir os links, ou seja, limita a comunicação dinâmica entre clientes e servidores

Ignoring Caching

Clientes REST e desenvolvedores backend tendem a evitar o cache devido à sua complexidade de implementação. No entanto, a capacidade de armazenamento em cache é uma das principais restrições de REST. Ao ignorar recursos de chace não usando Cache-Controe: no-cache ou no-store e não provendo um ETag no cabeçalho da resposta.

Ignoring MIME Types

O servidor deve representar recursos em vários formatos, por exemplo, XML, JSON, PDF, etc., o que pode permitir a clientes, desenvolvidos em qualquer linguagens, um consumo de serviço mais flexível. No entanto, os desenvolvedores backend geralmente pretendem ter uma única representação de recursos ou depender de seus próprios formatos, o que limita a acessibilidade e a reutilização do recurso (ou serviço).

Ignoring Status Code

Apesar de um rico conjunto de códigos de status de nível de aplicativo definidos adequados para vários contextos, os desenvolvedores REST tendem a evitá-los, ou seja, contam apenas com os comuns, a saber 200, 404 e 500, ou até mesmo usam os códigos de status errados ou nenhum. O uso correto dos códigos de status das classes 2xx, 3xx, 4xx e 5xx auxilia clientes e servidores a se comunicarem de forma mais semântica

Misusing Cookies

Statelessness é outro princípio REST a ser seguido - o estado da sessão no lado do servidor não é permitido e todos os cookies violam o RESTfulness. O envio de chaves ou tokens no campo de cabeçalho Set-Cookie ou Cookie para a sessão do lado do servidor é um exemplo de uso indevido de cookies, que diz respeito à segurança e privacidade

Tunnelling Through GET

Sendo o método HTTP mais fundamental em REST, o método GET recupera um recurso identificado por um URI. No entanto, muitas vezes os desenvolvedores usam apenas este método para realizar qualquer tipo de ação ou operação, incluindo a criação, exclusão ou até mesmo para atualizar um recurso. No entanto, HTTP GET é um método impróprio para qualquer ação diferente de acessar um recurso e não corresponde ao seu propósito semântico, se usado indevidamente.

Tunnelling Through POST

Esse Anti-Pattern é muito semelhante ao anterior, exceto que, além do URI, o corpo da solicitação HTTP POST pode incorporar operações e parâmetros a serem aplicados ao recurso. Os desenvolvedores tendem a depender apenas do método HTTP POST para enviar qualquer tipo de solicitação ao servidor, incluindo acesso, atualização ou exclusão de um recurso. Em geral, o uso adequado de HTTP POST é criar um recurso do lado do servidor. Qualquer paramêtro que altere uma requisição de informação, deve ser enviado como Query Parameter.

Domain Patterns

Early Directed URI (ED_URI)

Expressive Request (ER)

‘me’ Accessible Resources (MAR)

Metadata Retrievability (MR)

Proactive Filtering (PF)

Querified Authentication (QA)

Versionized API (V_API)

Versionized Resources (VR)

Conclusão

Design Patterns podem existir para qualquer área. Eles podem ser de grande ajuda se você os conhece, vão te dar repertórios tanto para novos desenvolvimentos, quando para melhorias em códigos já existentes. Eles também podem indicar pontos de melhoria no seu projeto.


Foto de Element5 Digital no Pexels

Biblioteca

Backend Roadmap

Padrões de Projetos para APIs REST?
Anatomia do Protocolo HTTP
Backend: O desenvolvedor invisível
Originally published November 30, 2020