em Tecnologia

Arquitetura, padrões e boas práticas

Quando desenvolvemos um serviço web, que alimentará com dados algum cliente (aplicativos, webapps ou qualquer outro sistema), precisamos prestar muita atenção no modelo de interface que utilizaremos.

Isso é importante para que os desenvolvedores que utilizarem seu serviço web tenham fácil compreensão do que cada endpoint faz, de acordo com o verbo HTTP utilizado para a requisição.

A maneira mais comum para modelar uma interface como essas nos dias de hoje é a arquitetura REST.

Antes de continuar, vamos para algumas definições importantes para seguirmos o assunto sem que tudo fique incompreensível para quem não é familiarizado com as expressões utilizadas nos primeiros parágrafos.

O que é API?

Interface de Programação de Aplicação, cujo acrônimo API provém do Inglês Application Programming Interface, é um conjunto de rotinas e padrões estabelecidos por um software para a utilização das suas funcionalidades por aplicativos que não pretendem envolver-se em detalhes da implementação do software, mas apenas usar seus serviços. (fonte Wikipedia)

No caso desse texto estamos falando especificamente sobre as APIs de serviço web, ou web services APIs, que são interfaces de programação para troca de dados via web, utilizando protocolo HTTP.

Isso é feito através de endpoints.

Os endpoints são os endereços web que executam as ações e são acessados diretamente pelos clientes.

O que é REST?

Representational state transfer (REST) or RESTful web services são uma forma de proporcionar interoperabilidade entre sistemas de computadores na Internet. Os serviços da Web compatíveis com REST permitem que os sistemas solicitantes acessem e manipulem representações textuais de recursos da Web usando um conjunto uniforme e predefinido de operações sem estado (stateless). (fonte Wikipedia)

Quando a arquitetura REST é aplicada à APIs de serviços web, chamamos de RESTful APIs.

E os verbos HTTP?

O protocolo HTTP define métodos (às vezes referidos como verbos) para indicar a ação desejada a ser realizada no recurso identificado. O que este recurso representa, se são dados pré-existentes ou dados gerados dinamicamente, depende da implementação do servidor. Muitas vezes, o recurso corresponde a um arquivo ou a saída de um executável residente no servidor. (fonte Wikipedia)

Em resumo, os verbos HTTP são os métodos de requisição que utilizamos para acessar os endpoints de uma RESTful API.

Uma das primeiras coisas que deve ser feita ao iniciar um projeto de API é planejar os endpoints que existirão para o acesso aos dados e para as ações específicas.

Segue um exemplo bem simples desse planejamento feito em uma planilha qualquer.

Vendo esse exemplo fica bem explícito o que cada verbo HTTP significa, certo?

Qualquer um que conheça essa arquitetura vai saber que o endpoint /users tem, no mínimo, essas opções de ação. Por isso é tão importante respeitar os verbos para facilitar o entendimento da sua API.

Vamos detalhar melhor cada um deles.

POST

O verbo POST é mais frequentemente utilizado para criar novos recursos. Na criação bem-sucedida, retornar o status HTTP 201.

Ele não é um método seguro, pois altera o estado do recurso no servidor. Ele também não é idempotente, o que quer dizer que se ele for executado duas vezes de forma idêntica serão criados dois itens diferentes com o mesmo conjunto de dados.

GET

O método HTTP GET é usado para ler ou recuperar uma representação de um recurso. Em caso de sucesso, retorna uma representação em JSON e um código de resposta HTTP de 200 (OK). Em caso de erro, ele geralmente retorna um 404 (NOT FOUND) ou 400 (BAD REQUEST).

De acordo com o design da especificação HTTP, requisições GET (juntamente com HEAD) são usadas apenas para ler dados e jamais alterá-los. Portanto, quando usados dessa forma, são considerados seguros.

Além disso, GET (e HEAD) é idempotente, o que significa que fazer várias solicitações idênticas acaba tendo o mesmo resultado de uma única solicitação.

PUT

PUT é mais utilizado para substituir (ou atualizar) recursos, executando a requisição para uma URI de recurso conhecido, com o corpo da requisição contendo a representação recém-atualizada do recurso original.

Na atualização bem-sucedida, retorna 200 (ou 204 se não retornar qualquer conteúdo no corpo). Retornar os dados do recurso no corpo é opcional, lembrando que fazer isso causa maior consumo de banda.

PUT não é uma operação segura, pois modifica estado no servidor, mas é idempotente. Em outras palavras, se você atualizar um recurso usando PUT e, em seguida, fazer essa mesma chamada novamente, o recurso ainda está lá e ainda tem o mesmo estado.

Obs: Se, por exemplo, executar uma requisição PUT em um recurso incrementar um contador (dentro do recurso), a chamada não é mais idempotente. É recomendado manter as solicitações PUT idempotentes. Use o POST para solicitações não idempotentes.

PATCH

PATCH é usado para modificar parcialmente os recursos. A requisição só precisa conter as alterações específicas para o recurso, não o recurso completo.

Se parece com PUT, mas o corpo contém um conjunto de instruções descrevendo como um recurso no servidor deve ser modificado para produzir uma nova versão.

PATCH não é nem seguro, nem idempotente.

DELETE

DELETE é bastante fácil de entender. Ele é usado para excluir um recurso identificado por um URI.

Na exclusão bem-sucedida, devolve o status HTTP 200 (OK) ou o status HTTP 204 (NO CONTENT) sem corpo de resposta.

Operações DELETE são idempotentes.

Há uma advertência sobre idempotência no DELETE. Chamar DELETE em um recurso uma segunda vez geralmente retornará um 404 (NOT FOUND) já que ele já foi removido e, portanto, não é mais encontrável. Isso, por algumas opiniões, faz operações DELETE não mais idempotente, no entanto, o estado final do recurso é o mesmo. Retornar um 404 é aceitável e comunica com precisão o status da chamada.

Obs: Se a requisição DELETE decrementa um contador (dentro do recurso), a chamada DELETE não é mais idempotente. É recomendável usar o POST para solicitações de recursos não idempotentes.

Os códigos de resposta (status codes) HTTP

Nas descrições dos verbos HTTP foram citados diversas vezes os status code do protocolo HTTP.

Esse é outro item importante para a arquitetura de uma API REST, porque, da mesma maneira que acontece como os verbos HTTP, elas formam um padrão facilmente reconhecido por quem for consumir o web service.

Os principais códigos utilizados para as respostas de um endpoint são o 200 (OK), o 201 (CREATED), o 204 (NO CONTENT), o 404 (NOT FOUND) e o 400 (BAD REQUEST).

Todos os códigos tem nomes autoexplicativos, portanto é muito simples lembrar o que utilizar em cada situação.

Existe uma lista enorme de códigos de resposta do protocolo HTTP que podem ser utilizados, como o 301 (MOVED PERMANETLY) e o 304 (NOT MODIFIED). Sendo o segundo para conteúdos em cache, por exemplo.

Os códigos de sucesso tem o padrão 20x, os de redirecionamento 30x, os de erro do cliente 40x e os de erro de servidor 50x.

Lembrando mais uma vez, os padrões facilitam qualquer desenvolvedor de entender facilmente o que aconteceu com o retorno da requisição que ele executou.

No caso de erros, mesmo tendo esses padrões, é importante devolver ao cliente uma mensagem clara do que aconteceu com a requisição e qual o motivo do erro.

Para ver mais detalhes sobre os códigos HTTP e também a lista completa deles, acesse o link https://httpstatuses.com/.

Concluindo

Este foi uma publicação mais teórica sobre a arquitetura, os padrões e algumas boas práticas no desenvolvimento de uma RESTful API.

Ainda existem muitos assuntos a serem abordados para quem quer se aprofundar mais nesse tipo de desenvolvimento, mas essa publicação ajuda a dar os primeiros passos.

Mas a melhor maneira de aprender de verdade é passando pela experiência de desenvolver uma API que seja consumida por alguns clientes, ou até criar um cliente que consuma uma API pública já existente.

Publicado originalmente no Medium.

Deixe um comentário

Comentário