Introdução às Boas Práticas em API REST


Olá pessoal!
Bem-vindos ao artigo desta semana. Você pode conferir os artigos anteriores aqui, e o código está disponível no meu GitHub, basta acessar aqui.
Vamos entender e aplicar algumas boas práticas em nossa API?
Este texto é um ponto de partida, onde vou citar algumas boas práticas, aplicar no código e fazer uma breve explicação que poderá ser utilizando como um roteiro de estudos.
Começando pelos verbos HTTP
Quando falamos de APIs REST, é muito importante saber usar os verbos HTTP do jeito certo. Por exemplo, usar um GET para criar algo ou um POST para buscar informações pode deixar a API confusa e difícil de entender, complicando o entendimento do consumidores desta API (outros desenvolvedores).
Vou fazer uma breve explicações dos verbos mais utilizados.
GET
É usado para buscar dados. No contexto da nossa API utilizamos este verbo em duas operações
Na operação de listar todas as séries cadastradas no banco de dados;
E para consultar os detalhes de uma série específica pelo seu ID.
POST
Serve para criar ou salvar um novo registro. No nosso cenário, usamos para adicionar uma nova série à base de dados.
PATCH
Esse verbo é usado para atualizar parcialmente um registro, ou seja, apenas os campos fornecidos na requisição são modificados, e os demais atributos permanecem inalterados. Na nossa API, utilizamos esse verbo para alterar o status de uma série (completa ou não) e para atualizar informações sobre as temporadas de uma série.
PUT
É utilizado para substituir completamente um registro. Isso significa que todos os campos do recurso devem ser enviados na requisição, mesmo os que não sofrerão alteração. Caso algum campo esteja ausente, ele pode ser apagado ou redefinido.
Não utilizamos esse verbo porque nossas atualizações são sempre parciais.
DELETE
Como o próprio nome sugere, é utilizado para excluir um registro. Na nossa API, ele é usado para remover uma série pelo ID.
Entendendo os Códigos de Status HTTP
Os códigos de status HTTP são respostas que o servidor envia para informar o resultado de uma requisição. Eles são divididos em classes baseadas no primeiro dígito do código:
1xx (Informational): Indica que a requisição foi recebida e está sendo processada.
- Exemplo: O servidor confirma o recebimento, mas ainda não concluiu a resposta.
2xx (Successful): Indica que a requisição foi concluída com sucesso.
200 (OK): Usado para requisições bem-sucedidas, como ao buscar (GET), atualizar (PATCH) ou deletar (DELETE) um recurso.
201 (Created): Indica que um recurso foi criado com sucesso, como ao criar algo via POST.
204 (No Content): Usado quando uma requisição (ex.: DELETE) é bem-sucedida, mas não há conteúdo para retornar.
3xx (Redirection): Indica que é necessário tomar outra ação para completar a requisição.
- Exemplo: Redirecionamento para uma nova URL.
4xx (Client Error): Ocorre quando há algo de errado na requisição feita pelo cliente.
400 (Bad Request): Indica que os dados enviados estão incorretos ou incompletos.
404 (Not Found): Retornado quando o recurso solicitado não existe, como buscar um ID que não está no banco de dados.
5xx (Server Error): Indica que ocorreu um erro no servidor ao tentar processar uma requisição aparentemente válida.
- Exemplo: 500 (Internal Server Error), que aponta um problema inesperado no servidor.
Para mais detalhes, consulte a RFC9110 e também o site Http Cat (Este site tem uma abordagem visual e divertida para aprender os códigos HTTP).
Separação Clara de Responsabilidades
Um ponto muito importante ao desenvolver uma API é separar bem as responsabilidades entre as camadas. Isso ajuda a manter o código limpo, organizado e fácil de manter.
A classe SeriesController é a porta de entrada das requisições e tem as seguintes responsabilidades:
Receber os dados de entrada;
Delegar a lógica para a camada de serviço (SeriesService)
Retornar as respostas com os códigos de status adequados, como 200 OK ou 201 Created.
A SeriesService fica responsável pela lógica de negócio. Essa camada:
Realiza as validações mais complexas;
Gera as exceções quando algo de errado acontece. Exemplo: Série não encontrada pelo ID informado;
Delega a lógica para o SeriesMapper (Responsável por mapear um DTO para Entidade e vice versa) e para o SeriesRepository;
E a SeriesRepository fica responsável por
- interagir com o banco de dados, sem implementar nenhuma regra de negócio.
Tratamento Centralizado de Erros
Por fim, outra boa prática para manter o código limpo e organizado é centralizar o tratamento de erros. Em vez de espalhar blocos de try-catch pelo código, criamos uma classe anotada com @ControllerAdvice, para gerenciar todas as exceções geradas na sua API.
Na API, por exemplo, utilizamos uma exceção chamada SeriesNotFoundException e quando uma série não é encontrada, essa exceção é lançada e tratada pela classe GlobalExceptionHandler. Isso garante que as respostas de erro sejam sempre consistentes, independentemente de onde a exceção foi gerada.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(SeriesNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleSeriesNotFound(SeriesNotFoundException ex) {
return ErrorResponse.builder()
.code(ex.getCode())
.message(ex.getMessage())
.timestamp(LocalDateTime.now())
.build();
}
}
Essas boas práticas são um ótimo ponto de partida para quem quer criar APIs.
E você, tem alguma dica ou boa prática que não abre mão? Compartilhe nos comentários!
Até a próxima! 🚀😊
Subscribe to my newsletter
Read articles from Robert Adam directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
