39 pontos por GN⁺ 2025-08-25 | Ainda não há comentários. | Compartilhar no WhatsApp
  • Em engenharia de software, APIs são uma ferramenta central, e uma característica desejável de uma boa API é ser familiar e simples a ponto de parecer entediante
  • Como uma API, depois de publicada, é difícil de mudar, o princípio de não quebrar o ambiente do usuário (WE DO NOT BREAK USERSPACE) é importante
  • Quando a mudança for inevitável, é necessário versionamento (versioning), mas isso é um mal necessário que aumenta bastante a complexidade e o custo de manutenção
  • A qualidade da API acaba dependendo do valor do próprio produto, e um produto mal projetado dificulta a criação de uma boa API
  • Para estabilidade e escalabilidade, vale considerar autenticação baseada em chave de API, idempotência, rate limiting e paginação baseada em cursor

Introdução: a importância e o contexto do design de APIs

  • Uma das principais atividades de engenheiros de software modernos é interagir com APIs
  • O autor também tem experiência em projetar/implementar/utilizar APIs públicas e internas em várias formas, como REST, GraphQL e ferramentas de linha de comando
  • Os conselhos existentes sobre design de APIs tendem a se apegar a conceitos complexos (definição de REST, HATEOAS etc.)
  • Este texto organiza princípios práticos de design de APIs com base em experiência real

Equilíbrio entre familiaridade e flexibilidade: a primeira condição de uma boa API

  • Uma boa API é uma API “comum e entediante”, ou seja, seu modo de uso deve ser parecido com o de APIs que as pessoas já encontraram antes
  • Como o usuário quer se concentrar em atingir o próprio objetivo, e não na API em si, é preciso um design com baixa barreira de entrada
  • Uma vez publicada, uma API é muito difícil de alterar, então é preciso cuidado desde a fase inicial de projeto
  • Desenvolvedores querem APIs o mais simples possível, mas sempre existe a preocupação de preservar flexibilidade no longo prazo
  • No fim, a questão central é o equilíbrio entre familiaridade e flexibilidade de longo prazo

Nunca quebrar o espaço do usuário (WE DO NOT BREAK USERSPACE)

  • Em geral, mudanças que adicionam campos à estrutura de resposta não causam problema
  • remover campos ou mudar tipos e estruturas acaba quebrando o código de todos os consumidores
  • Quem mantém a API tem a responsabilidade de não estragar deliberadamente o software dos usuários existentes
  • Até o erro de grafia no header HTTP "referer" não é corrigido por causa dessa cultura de preservar o espaço do usuário

Como mudar sem quebrar a API: estratégia de versionamento

  • Mudanças quebrando compatibilidade na API só devem ser permitidas quando forem realmente necessárias, e nesse caso a resposta é versionamento
  • É preciso operar a versão antiga e a nova ao mesmo tempo, induzindo uma transição gradual
  • Identificadores de versão podem ser usados de várias formas, como URL (/v1/) ou headers, e os usuários podem migrar no próprio ritmo
  • O versionamento tem desvantagens como enorme custo de manutenção (mais endpoints, testes, suporte) e confusão para o usuário
  • Mesmo usando uma camada interna de tradução como a Stripe, a complexidade fundamental não pode ser evitada
  • Introduzir versionamento na API deve ser o último recurso

O sucesso da API depende totalmente do valor do produto

  • Uma API é, em essência, apenas a interface de um produto de negócio real
  • Mesmo APIs como OpenAI e Twilio são, no fim, casos em que o usuário queria a funcionalidade em si oferecida pela API
  • Se o produto tiver valor, as pessoas o usarão mesmo que a API seja incômoda
  • A qualidade da API é uma característica “marginal”: só vira fator de escolha quando a competitividade essencial é parecida
  • Por outro lado, um produto sem API é uma grande barreira para usuários técnicos

Se o design do produto for ruim, a API também não pode ser boa

  • Mesmo que exista uma API tecnicamente muito bem feita, isso não significa muito se o produto não tiver apelo de mercado
  • Mais importante ainda: se a estrutura básica dos recursos for ilógica ou ineficiente, isso aparece na API também
  • Por exemplo, um sistema que armazena comentários como lista encadeada dificulta até mesmo um design RESTful natural
  • Problemas técnicos que podem ficar escondidos na UI ficam todos expostos na API, forçando desnecessariamente o usuário a entender o sistema interno

Autenticação (Authenticaton) e diversidade de usuários

  • É preciso oferecer suporte obrigatório a autenticação baseada em chaves de API de longa duração
  • Mesmo que se dê suporte adicional a métodos mais seguros como OAuth, a barreira de entrada da chave de API é muito menor
  • Consumidores de API não são apenas engenheiros; há também não desenvolvedores (vendas, planejamento, estudantes, hobbyistas etc.)
  • Exigências de autenticação difíceis ou complexas (como OAuth) viram barreira para usuários não especialistas

Idempotência e tratamento de retries

  • Em requisições de ação (por exemplo, pagamento, mudança de estado etc.), é importante garantir segurança para retry em caso de falha
  • Idempotência significa garantir que, mesmo enviando a mesma requisição várias vezes, o resultado seja processado apenas uma vez
  • O método padrão é passar uma "chave de idempotência" em parâmetro ou header para evitar processamento duplicado
  • Para armazenar a chave de idempotência, um armazenamento simples de chave/valor como Redis é suficiente, e na maioria dos casos dá para aplicar expiração periódica sem problema
  • Em geral, isso não é necessário para requisições de leitura/remoção (no estilo REST)

Segurança da API e rate limiting

  • Requisições de API por código podem acontecer muito mais rápido do que interações manuais de usuários
  • Uma única API publicada sem muita atenção pode acabar sendo usada de forma inesperada (por exemplo, em um sistema de chat em larga escala)
  • Rate limiting é indispensável, e deve ser aplicado de forma mais rígida em operações com custo elevado
  • Uma desativação temporária da API para um cliente específico (killswitch) também deve ser considerada como opção
  • É preciso informar dados de rate limiting por meio de headers de resposta como X-Limit-Remaining e Retry-After

Estratégia de paginação

  • Para retornar grandes conjuntos de dados com eficiência (por exemplo, milhões de tickets), paginação é essencial
  • Paginação baseada em offset é simples, mas vai ficando lenta em grandes volumes de dados
  • Paginação baseada em cursor funciona bem até em datasets muito grandes, sem degradação da performance da query
  • A abordagem com cursor é um pouco mais difícil de implementar e usar, mas no longo prazo tem grande chance de se tornar uma mudança obrigatória
  • É sensato incluir no response um campo como next_page, orientando claramente qual cursor usar na próxima requisição

Campos opcionais e opinião sobre GraphQL

  • Campos custosos ou lentos devem ficar fora da resposta padrão e ser adicionados opcionalmente só quando necessário
  • É possível incluir dados relacionados com um parâmetro como includes
  • GraphQL tem a vantagem da flexibilidade na estrutura de dados, mas traz problemas como menor acessibilidade para não desenvolvedores, maior complexidade de cache/casos de borda e maior dificuldade de implementação no backend
  • Pela experiência prática, adotar GraphQL é apropriado apenas quando realmente necessário

Características de APIs internas

  • APIs internas têm várias condições diferentes das APIs externas (públicas)
  • Como os consumidores são em sua maioria engenheiros de software profissionais, autenticação mais complexa e mudanças incompatíveis podem ser aceitáveis
  • Ainda assim, os princípios de projeto voltados a idempotência, prevenção de incidentes e redução da carga operacional continuam válidos

Resumo

  • APIs têm a característica de serem difíceis de mudar e fáceis de usar
  • Não quebrar o espaço do usuário é o dever mais importante de quem mantém uma API
  • Versionamento de API tem custo alto, então deve ser usado apenas como último recurso
  • No fim, a qualidade da API é determinada pelo valor essencial do produto
  • Um produto mal projetado tem limites grandes, mesmo que se tente compensar isso no nível da API
  • É importante oferecer métodos simples de autenticação, garantir idempotência em requisições de ação indispensáveis e adotar medidas de estabilidade como rate limiting e paginação
  • APIs internas têm estratégias diferentes conforme o uso e o público, mas ainda exigem cuidado no design
  • REST, JSON, OpenAPI e formatos semelhantes não são o ponto essencial. Uma documentação clara é mais importante

Ainda não há comentários.

Ainda não há comentários.