en
· 4 min de leitura

Contratos antes do código

Escreva a interface, o schema e os casos de falha antes da primeira linha de implementação. É a revisão de design mais barata que existe.

architectureengineering

A hora mais produtiva de qualquer projeto que liderei é aquela em que ninguém escreve código de implementação. É a hora em que escrevemos o que um componente vai aceitar, o que vai devolver, o que vai emitir e como vai falhar, e depois discutimos isso antes de existir o corpo de uma única função.

Isso não é sobre documentação e não é sobre cascata. É sobre fazer o design onde as mudanças são baratas, num arquivo de texto, em vez de onde são caras, em três serviços e uma migração.

O que é um contrato

Um contrato é o comportamento externo completo de um componente, escrito de forma que duas pessoas que nunca conversam consigam construir os dois lados. Para uma API HTTP, é um documento OpenAPI. Para um evento, é o schema do payload com o significado de cada campo. Para um módulo dentro de um monólito, é a interface TypeScript da superfície pública mais um parágrafo por função dizendo o que acontece em caso de falha.

As partes que mais importam são as que os times pulam. Quais erros isso pode devolver e o que cada um significa para quem chama? Quais campos são opcionais agora e quais sempre estarão presentes? Qual é o comportamento de idempotência quando a mesma requisição chega duas vezes? Quais são os limites: tamanho de página, tamanho de payload, taxa? Qual é a garantia de ordem, se houver? Um contrato sem isso é um caminho feliz com nome.

Por que antes do código

Três motivos, e já vi os três pouparem semanas.

Primeiro, o contrato expõe desacordos enquanto são baratos. O frontend esperava uma lista; o backend planejou um cursor paginado. O time mobile precisava do total; o backend não planejava calculá-lo. Descoberto numa revisão de contrato, é uma conversa de dez minutos. Descoberto depois de os dois lados entregarem, é uma nova versão e um pedido de desculpas.

Segundo, o contrato destrava o trabalho em paralelo. Uma vez que o formato está acordado, o frontend constrói contra um mock, o backend constrói contra um teste, e o teste de integração pode ser escrito por quem estiver livre. Sem o contrato, todo mundo espera pelo lado mais lento.

Terceiro, o contrato é o teste. Um schema pode ser validado em tempo de execução. Um documento OpenAPI pode gerar um cliente e um conjunto de testes de contrato que falham o build quando a implementação desvia. O artefato de design vira a coisa que mantém a implementação honesta, permanentemente.

A revisão de contrato

A revisão é onde está o valor, e deveria levar menos de uma hora para a maioria dos componentes. Faço um conjunto fixo de perguntas.

  • O que acontece quando cada entrada obrigatória está faltando, vazia ou malformada?
  • O que quem chama vê quando a dependência por trás disso está fora?
  • Qual é a resposta para a mesma requisição duas vezes?
  • Quais campos serão adicionados depois, e como os clientes antigos vão sobreviver a eles?
  • Qual é o maior payload, a lista mais longa, o caso mais lento, e o que acontece nesse limite?
  • Quem consome isso, e essa pessoa leu?

A última pergunta é a mais pulada. Um contrato que ninguém do lado consumidor leu é um chute. Peço que um consumidor nomeado aprove, mesmo informalmente, antes de a implementação começar.

Onde os contratos dão errado

A primeira falha é escrever o contrato depois do código e chamar de documentação. Isso produz uma descrição precisa do que a implementação por acaso fez, incluindo seus acidentes, e nenhuma pressão de design.

A segunda é especificar demais. Um contrato que dita estrutura interna, colunas de banco ou escolhas de implementação não é um contrato, é um documento de design fantasiado, e prende quem implementa à primeira ideia de quem revisou. O contrato deveria descrever comportamento visto de fora e nada mais.

A terceira é deixar apodrecer. Um contrato que não é imposto por testes desvia em um mês. Se o schema não valida requisições em tempo de execução e o CI não compara a implementação com a especificação, o contrato é um desejo.

Escreva a interface primeiro. Discuta por uma hora. Faça um consumidor ler. Gere os testes a partir dela. Depois escreva o código, que será menor e mais claro do que seria, porque as decisões difíceis já foram tomadas.