Ao longo do tempo, o desenvolvimento de software sempre se deparou com problemas, tais como falha na reutilização do código, complexidade no design, baixa manutenção, modularidade e acoplamento, escalabilidade entre outros.
Esses problemas culminaram no trabalho da "Gangue dos 4" (Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides), que publicou o clássico livro Design Patterns: Elements of Reusable Object-Oriented Software (1994). Esse livro definiu 23 padrões que abordam problemas comuns no design orientado a objetos, consolidando a ideia de que o software pode ser projetado de maneira mais eficiente e sustentável.
Basicamente, os padrões de projeto (Design Patterns) são soluções reutilizáveis que ajudam os desenvolvedores a resolverem problemas comuns e recorrentes no design de software. Eles fornecem abordagens testadas e comprovadas para criar código flexível e de fácil manutenção.
Na década de 1990, a internet começa a se consolidar nos moldes do que temos hoje e desta forma, surgiram as aplicações voltadas para atender a essa demanda.
Surge então a API (em português: Interface de Programação de Aplicação), que é um conjunto de rotinas e padrões estabelecidos por um software para utilização de suas funcionalidades por aplicativos que não pretendem envolver-se em detalhes da implementação dele, mas apenas utilizar suas funcionalidades.
De forma corporativa, a construção de uma API se dá através das Web APIs e podem seguir a arquitetura REST ou serem apenas baseadas em HTTP. Mais adiante, tratarei a diferença entre uma aplicação baseada em HTTP e a que usa a arquitetura REST.
Web API é uma forma de construção de APIs onde a troca de informações (request e response) é feita através do protocolo de transporte HTTP. O foco é enviar dados pré-estabelecidos pela API e receber a resposta para apresentação pelo client.
- Client pode significar um mobile, console app, HTML/Javascript nativo, outra API em outro tecnologia, frameworks Javascript como React, Angular, Vue, Next e o novo modelo de front-end da Microsoft: o Blazor.

É lógico imaginarmos que ao longo desses últimos 35 anos, o desenvolvimento para aplicações web se deparasse com os mesmos problemas enfrentados no desenvolvimento dos softwares, principalmente no que se diz respeito ao HTTP e suas requisições e respostas (request/response).
O meu intuito com esse artigo é falar justamente dessas questões e apresentar o API Design Patterns. A adoção de padrões de design ajuda a mitigar esses problemas, tornando as APIs mais confiáveis e fáceis de usar, oferecendo uma série de benefícios significativos na sua criação e manutenção.
Mas antes, deixe-me contar como eu cheguei nesse artigo.
Como cheguei até aqui
Eu trabalho com o desenvolvimento de APIs há algum tempo. Em todo tipo de software em que trabalho, busco a organização, as boas práticas e os padrões. Então, comecei a buscar e consumir conteúdos relacionados.
Foi nessa busca que comecei a ler sobre um API Design Patterns. O conceito e informações não estavam em apenas um artigo, mas em diversos lidos até aquele momento e como eu tenho o hábito da organização, fui criando um documento onde ordenei as informações para facilitar a compreensão.
Até que em maio/2020, início do lockdown, eu fui contratado pela Sensedia – https://www.sensedia.com. E nela, eu encontrei um documento falando sobre API Design Patterns bem organização. Para quem não sabe, a Sensedia é idealizadora e mantenedora, atualmente, do maior evento sobre o desenvolvimento de API do mundo. Trata-se do APIX – https://www.sensedia.com.br/apix, um evento global e que conta inclusive com participações de nomes internacionais. Se você quer trabalhar com API ou já trabalha, mas não conhecia este evento. Não pode ficar de fora do próximo.
Na ANP – Agência Nacional do Petróleo, Gás Natural e Biocombustíveis, tive a oportunidade de, como Arquiteto, orquestrar a modernização do CSA – Centra de Sistemas ANP https://csa.anp.gov.br. A API foi totalmente construída utilizando os conceitos apresentados neste artigo.
E é com base nas minhas experiências, que trago esse artigo para vocês.
Problemas recorrentes nas APIs
APIs que não aplicam padrões de design frequentemente sofrem com problemas recorrentes, tais como:
- Documentação Insuficiente: APIs sem documentação clara dificultam o uso correto e a integração por parte dos desenvolvedores.
- Convenções de Nomenclatura Inconsistentes: Nomes de endpoints, parâmetros e recursos devem seguir padrões consistentes para facilitar a compreensão.
- Complexidade Excessiva: APIs com muitos endpoints, parâmetros ou opções podem se tornar confusas e difíceis de usar.
- Falta de Versionamento: Sem versionamento adequado, mudanças na API podem quebrar aplicativos existentes.
- Segurança Frágil: APIs sem autenticação robusta ou proteção contra ataques, são vulneráveis a ameaças.
Para mitigar esses problemas, devemos adotar o API Design Patterns, oferecendo uma série de benefícios significativos.
Benefícios da adoção de padrões de design de API
- Consistência: Padrões bem definidos simplificam a compreensão e utilização da API, tornando-a mais amigável para desenvolvedores e promovendo uma curva de aprendizado mais suave.
- Interoperabilidade: Ao seguir padrões estabelecidos, as APIs se tornam mais interoperáveis, permitindo uma integração mais fácil com outros sistemas e serviços.
- Flexibilidade e Escalabilidade: As APIs podem ser combinadas e estendidas de maneira mais eficiente, facilitando o desenvolvimento de aplicativos robustos e adaptáveis.
- Segurança e Qualidade: A conformidade com padrões ajuda a garantir a segurança e a qualidade das APIs, contribuindo para uma experiência de usuário mais confiável e consistente.
Portanto, a adoção de padrões de design de API é essencial para promover o sucesso e a sustentabilidade de projetos de desenvolvimento de software.
Como arquiteto, eu sigo a linha de raciocínio que diz:
"O desafio é reduzir o custo/risco da mudança ao longo do tempo." – Elemar Jr.
URI – Uniform Resource Identifier
As URIs (Uniform Resource Identifiers) desempenham um papel crucial no padrão de design de API, fornecendo identificadores únicos para recursos na web. Ao seguir esse padrão, as URIs são projetadas de forma consistente e significativa, refletindo a estrutura hierárquica dos recursos da API. Isso facilita a navegação e a compreensão da API, tornando-a mais amigável para desenvolvedores e promovendo uma experiência coesa do usuário.
Além disso, URIs bem projetadas contribuem para a interoperabilidade, facilitando a integração com outras APIs e sistemas, promovendo a escalabilidade e a manutenção eficiente. Portanto, as URIs, quando seguem o padrão de design de API, desempenham um papel fundamental na criação de APIs eficazes e consistentes.
Devemos seguir uma estrutura para a URI. Mas qual estrutura? Então... depende.
Os elementos mínimos de URI são:
- Nome da api
- Domínio
- Versão maior – pode ser opcional
- Recurso
Nota: Você só deve considerar a ausência de um versionamento, se tiver certeza que não há razão para futuras implementações.
Na ANP – Agência Nacional do Petróleo, Gás Natural e Biocombustíveis, eles também possuem o elemento do ambiente. Seguem a seguinte estrutura:
- https://nome-api.ambiente.dominio/{versão_maior}/recurso O ambiente não existe na URI de produção. Aqui a API está definida como um subdomínio.
Outra possibilidade:
- https://ambiente.dominio/nome-api/{versão_maior}/recurso Nessa possibilidade, a API está definida como uma aplicação dentro do domínio.
Dependendo do seu design, você pode precisar acrescentar um novo elemento à sua URI. Digamos que seu design tenha uma separação por camada – que pode ter outros nomes como módulo ou contexto. Então, adicione esse elemento antes do “recurso”.
- https://nome-api.dominio/{versão_maior}/camada/recurso
Recursos
Obviamente, o que há de mais importante em nossa API, pois se trata dos nossos dados. Representam as entidades – concretas ou abstrata, que fazem parte do nosso domínio.
Eis alguns exemplos:
- Usuário
- Solicitação
- Perfil
- Produto
De tão importantes, devemos ter certos cuidados com eles, tipo padrões, idiomas, grafia. Vamos vê-los.
Padrões de nomenclatura
Seguir um padrão, significa permitir que a equipe atual e os novos membros tenham mais tranquilidade durante todo o processo de desenvolvimento, acelerando o entendimento do código e consequentemente, facilitando a manutenção. Lembrando que precisamos nos preocupar com a mudança ao longo do tempo.
Essas são as melhores práticas:
- Os nomes dos recursos devem ser em letras minúsculas e respeitar o padrão “spinal-case”, também conhecido como “kebab-case”, separando as palavras compostas com hífen;
- Não devem conter acentuação, espaços ou caracteres especiais;
- Não devem conter preposições (do, de, com, para, etc.);
- Não colocar ação ou formato de mídia.
Exemplo:
- https://nome-api.dominio/v1/login CERTO
- https://nome-api.dominio/v1/acessos/termos-aceite CERTO
- https://nome-api.dominio/v1/Login ERRADO
- https://nome-api.dominio/v1/acessos/TermosAceite ERRADO
Legibilidade é mais importante do que o tamanho do nome do recurso. Há sempre um questionamento entre o tamanho da URI e a legibilidade, considere sempre que possível a legibilidade.
Evite abreviações e siglas. Exceções devem restringir-se apenas para siglas, acrônimos e abreviações conhecidos ou inerentes ao negócio do departamento ou da corporação. Por exemplo, Id (identificador), CPF (Cadastro de Pessoa Física), etc.
Exemplos de legibilidade:
- https://www.mercadolivre.com.br/bicicleta-aro-26-retro-vintage-antiga-caicara-classic-beach-cor-marrom-tamanho-do-quadro-unico/p/MLB22342987
- https://www.amazon.com.br/Benexmart-Sunrise-Wake-Up-Digital-Controle/dp/B093WM81VL
- https://www.pontofrio.com.br/geladeira-midea-md-rt468mta-frost-free-com-smart-sensor-e-painel-touch-347-l-branca-55058631/p/55058632
- https://www.tabnews.com.br/obrunoanastacio/proibido-para-seniors-encontrando-um-uso-de-verdade-para-tabelas-verdade
Exemplo ruim, pois inclui caracteres especiais da URI, como %C3:
- https://www.amazon.com.br/Gram%C3%A1tica-Met%C3%B3dica-Portuguesa-Napole%C3%A3o-Almeida/dp/8502054309
Idioma
A modelagem das APIs deve ser o mais simples e intuitivo para seus consumidores e, com maior abrangência, o idioma dos recursos deverá seguir o direcionamento da área de negócio, devendo seguir o negócio, pois tem relação direta com o público final desta API.
Quando trabalhei na ANP, o óbvio foi seguirmos o português. Motivação:
- ANP é uma Entidade Governamental Brasileira
- As pessoas envolvidas no desenvolvimento e sustentação são brasileiras
- Área de atuação nacional
Exemplo: (não faz sentido trazer esses termos para o inglês, no caso da ANP.
- Bacia
- Empresa
- Posto
- Combustivel
Nota: O inglês pode e até pode/deve ser aplicado em questões técnicas envolvendo padrão de projetos, como o termo “repository”, tipo BaciaRepository. E sim: não vejo problema nessa mescla dos idiomas. Não se esqueça que em tudo devemos considerar o "depende". E tem partes da aplicação que podem e até devem ser exclusivamente em inglês, por se tratar de uma questão puramente técnica envolvendo algum padrão já reconhecido na comunidade de softwares.
Substantivos vs Verbo
As URIs representam recursos a serem acessados e manipulados, e não ações. Com isso, as URIs devem conter apenas substantivos. As ações são representadas através das operações (métodos HTTP), que será detalhado no tópico “Operações” desse artigo.
Exemplo:
- https://nome-api.dominio/v1/pedidos – CERTO
- https://nome-api.dominio/v1/obterPedidos – ERRADO
- https://nome-api.dominio/v1/pedidos/alterar – ERRADO
Pode acontecer de termos alguma necessidade diferenciada, quando um recurso modela um conceito procedural. Os recursos são como funções executáveis, com parâmetros e valores de retorno; entradas e saídas.
Devemos analisar com cuidado para utilizar esse formato somente quando realmente necessário. Por exemplo: uma ação que “pertença” ao grupo de ações do CRUD, não se enquadra nesse formato.
Exemplo válido:
- https://nome-api.ambiente.dominio/v1/gerencia-carrinho/usuarios/{id}/carrinho/conferir (checkout)
Plural vs Singular
Aqui, temos alguns casos. Vamos vê-los.
Camada/módulo/contexto
Dependendo do caso, um módulo pode ficar no singular ou plural
Exemplos:
- https://nome-api.ambiente.dominio/v1/acessos/usuarios
- https://nome-api.ambiente.dominio/v1/gerencia-carrinho/usuarios/{id}/carrinho/conferir (checkout)
Área
A área tem o objetivo de facilitar a divisão do negócio. Este é um elemento da URI não mencionado anteriormente. Veja que ele vem antes da versão_maior.
Exemplo:
- https://nome-api.dominio/financeiro/v1/usuarios
Coleções de objetos/entidades
Considerando que os recursos, normalmente, representam um conjunto de entidades, seu nome deve ser sempre no plural.
Exemplo:
- https://nome-api.dominio/v1/pedidos – CERTO
- https://nome-api.dominio/v1/pedido – ERRADO
Objeto/entidade de uma coleção
Como dito anteriormente, os recursos representam conjuntos de entidades, com isso, para referir-se a um registro específico desse conjunto, utilizamos um identificador do elemento para recuperá-lo.
Nota: Esses identificadores (IDs) são o que chamamos de “path parameters”. Os IDs são do tipo número ou um GUID/UUID, porém, não é impeditivo utilizar outros identificadores que sejam únicos, como CPFs, CNPJs, e-mails, logins e até mesmo um nome ou título, como acontece em aplicações do tipo blog e e-commerce.
Exemplo:
- https://csaapi.anp.gov.br/v1/pedidos/{id}
- https://csaapi.anp.gov.br/v1/pedidos/123Nesse caso, estamos nos referindo ao pedido de Id “123”.
Documento de um objeto/entidade
Há casos em que é necessário retornar um elemento que faz parte de um recurso, tipo um “documento”. Este pode estar no singular.
Exemplo:
- https://nome-api.dominio/v1/usuarios/{id}/perfil
- https://nome-api.dominio/v1/gerencia-carrinho/usuarios/{id}/carrinho/conferir (checkout)
Sub-recurso
Um recurso pode conter sub-recursos que também podem ser representados na URI da API.
O que se aplica aos recursos, também se aplica aos sub-recursos.
Exemplo:
- https://nome-api.dominio/v1/pedidos/123/itensNesse caso, estamos nos referindo a lista de itens do pedido de Id “123”.
Query parameters
O componente de query da URI também representa a identificação exclusiva do recurso e a seguir estão as regras sobre consultas de URI:
- Sempre serão opcionais;
- Não devem conter acentuação, espaços ou caracteres especiais;
- Não devem conter preposições (do, de, com, para, etc.);
- O padrão de escrita deve ser o camelCase
Exemplo:
- https://nome-api.ambiente.dominio/v1/empresas?razaoSocial=Petrobras
Nota: paginação e filtros de pesquisa são bons exemplos de query parameters opcionais.
Operações
Verbos HTTP
O protocolo HTTP possui sete verbos/operações. São os métodos GET, POST, PATCH, PUT, DELETE, HEAD, OPTIONS e TRACE. Duas delas (GET e POST) já são bem conhecidas e utilizadas: GET quando clicamos em links ou digitamos o endereço no navegador, e POST quando preenchemos e enviamos o formulário de algum site.
Uma URI pode ser acessada utilizando cada um dos sete métodos HTTP citados acima e com essa combinação (URI + método) conseguimos representar todas as ações do nosso sistema. As semânticas principais são:
- GET: Recupera informações do recurso, normalmente associado ao Read do CRUD.
- POST: Cria um recurso novo, normalmente associado ao Create do CRUD. Este método além de criar um recurso novo também pode ser utilizado para execução de uma tarefa. Por exemplo, realizar o fechamento de uma fatura, pedido ou realizar a autenticação de um usuário (tais exemplos não estão relacionados a um INSERT no banco de dados, e sim a uma execução de tarefa cujo resultado pode ser variável). Nota: Ele também pode ser utilizado para realizar uma consulta, que possui um ou mais campos/parâmetros obrigatórios.
- PATCH: O método HTTP Patch é utilizado para realizar atualizações parciais de recursos. Por exemplo, quando é necessário atualizar um único campo de um recurso ao invés de todos os dados do recurso.
- PUT: Atualiza um recurso, normalmente associado ao Update do CRUD.
- DELETE:: Exclui um recurso, normalmente associado ao Delete do CRUD.
- HEAD, OPTIONS e TRACE: Recuperam metadados da URI passada, normalmente não são utilizados para APIs.
Exemplos:
Vamos unir tudo que vimos até agora, analisando o comportamento da URI e os verbos HTTP.
https://nome-api.dominio/v1/pedidos
- GET – Lista os pedidos
- POST – Cria um pedido novo
- PUT, DELETE, PATCH – Erro HTTP status code 405 *
https://nome-api.dominio/v1/pedidos/123
- GET – Exibe detalhes do pedido 123
- POST – Erro HTTP status code 405 **
- PUT – Atualiza o pedido 123
- DELETE – Exclui o pedido 123
- PATCH – Atualiza parcialmente o pedido 123
https://nome-api.dominio/v1/pedidos/123/itens
- GET – Lista os itens do pedido 123
- POST – Cria um item no pedido 123
- PUT, DELETE, PATCH – Erro HTTP status code 405 *
* A operação não deve ser implementada em coleções, então espera-se um erro com HTTP Status Code 405 (mais detalhes no tópico “HTTP Status Code Definitions” desse documento)
** O método não deve ser implementado em elemento, então espera-se um erro com HTTP Status Code 405 (mais detalhes no tópico “HTTP Status Code Definitions” desse documento)
Safe and Idempotent
Método HTTP | Idempotente | Seguro |
---|---|---|
GET | sim | sim |
POST | não | não |
PATCH | não | não |
PUT | sim | não |
DELETE | sim | não |
Safe (Seguro)
Métodos HTTP que não modificam os recursos, são fortes candidatos a fazer uso de cache.
Idempotent (Idempotente)
Método HTTP que pode ser chamado várias vezes sem resultados diferentes. O resultado deve ser o mesmo, porém, isso só se aplica ao resultado e não ao próprio recurso, ou seja, pode-se enviar uma requisição várias vezes (retry) com segurança até que se obtenha uma resposta satisfatória.
Exemplo:
- Idempotente: A = 4, n x n = n
- Não Idempotente: A++
Exemplos práticos
Abaixo, eu apresento alguns exemplos mais práticos e que foram aplicados na ANP. A aplicação é pública e possui um bom nível de segurança.
Note que incluímos um “módulo” acessos antes do recurso.
Nota: todas as URIs que possuem o CNPJ como path parameter, tem um tratamento especial confirmada via token de autenticação.
Verbo | URI | Descrição |
---|---|---|
GET | acessos/sistemas | Obtém os Sistemas ANP controlados pelo CSA, para montar a combobox Sistemas em Adicionar ou Alterar usuário |
GET | acessos/sistemas/{id}/perfis | Obtém os Perfis para o Sistema ANP selecionado na combobox Sistemas, para montar a combobox Perfis em Adicionar ou Alterar usuário. |
GET | acessos/motivos-exclusao | Obtém os Motivos de exclusão, para montar a combobox ‘Motivos exclusão’ em Excluir usuário. |
GET | acessos/{cnpj}/usuarios/ | Obtém os Usuários para um CNPJ |
GET | acessos/{cnpj}/usuários/{login}/perfis/ | Obtém os Perfis de um Usuário de um CNPJ |
GET | acessos/pessoas-fisicas/{cpf} | Obtém os dados de uma pessoa física |
GET | acessos/{cnpj}/termos-aceite | Obtém o Termo de Aceite de um CNPJ |
POST | acessos/{cnpj}/usuários/ | Adiciona um Usuário e seu perfil para um CNPJ |
POST | acessos/{cnpj}/usuarios/{login}/perfis/ | Adiciona perfis para um usuário de um CNPJ |
POST | acessos/{cnpj}/termos-aceite | Adiciona termo de aceite para um CNPJ |
DELETE | acessos/{cnpj}/usuarios/{login}/ | Exclui um usuário de um CNPJ |
DELETE | acessos/{cnpj}/usuarios/{login}/perfis/{perfil}/ | Exclui um perfil do usuário de um CNPJ |
Nos próximos artigos, irei abordar as definições do HTTP Status Code, HATEOAS, Problem Detail e Standardized Response.
Até lá.