Pular para o conteúdo

7. Padrões · versão 2.0.0

Backend e API

manifesto/architecture/05-backend.md

Aplica-se quando a ADR entrega lógica de servidor. A stack está em Backend (stack); aqui estão os padrões de construção e a régua contra over-engineering.

Princípio: comece simples

Um endpoint pode ser um único arquivo: a Route Handler do Next.js valida com Zod, chama o Prisma e responde. Sem controller, sem service, sem repository. Não se cria camada por hábito — camada nova só entra quando paga o próprio custo (princípio 1, hipersimplicidade).

A régua para subir de camada é complexidade real, não estética. Se o arquivo continua legível e a lógica cabe na cabeça, ele fica como está.

Padrão mínimo (o default)

Uma rota = um arquivo. Dentro dele, na ordem:

  1. Validação Zod da entrada — antes de qualquer processamento (princípio 7).
  2. Checagem de autenticação/autorização específica daquela rota — quem pode chamar isso, sobre quais recursos. O middleware genérico não decide isso por você.
  3. Lógica — Prisma direto na rota é aceitável quando a lógica é direta (CRUD, leitura simples, escrita simples com 1-2 regras).
  4. Resposta tipada conforme o schema Zod de saída.

Esse é o caminho padrão. A maioria dos endpoints fica assim e deve ficar assim.

Quando subir de camada (e só então)

Adicione a camada quando o sintoma aparecer, não antes:

  • Extrair um service — quando a mesma lógica de negócio é usada por mais de uma rota, ou quando a rota passa de ~50-80 linhas com regras de domínio que merecem teste unitário próprio.
  • Extrair um repository/dao — quando há consultas Prisma complexas, reaproveitadas, ou uma fronteira clara de persistência que o domínio quer ignorar. Para CRUD simples, não vale a pena.
  • Extrair um controller — raramente. Em Next.js a Route Handler já é o controller. Só faz sentido se houver orquestração não-trivial e reuso entre rotas.
  • Middleware — para concerns transversais (autenticação base, logging, rate-limit, CORS). Útil e recomendado, mas: o middleware autentica; quem autoriza a operação específica (esta conta pode editar este pedido?) é a rota. Misturar essas duas decisões no middleware é um anti-padrão — a regra fica longe do código que ela protege.

Estrutura de referência (opcional)

Quando o projeto cresce e várias rotas já justificaram quebras, esta organização funciona bem. Não é regra; é onde as coisas costumam parar quando precisam parar em algum lugar:

config/ ← configuração de banco, variáveis de ambiente, segurança
routes/ ← Route Handlers (o endpoint em si)
services/ ← lógica de negócio reusada por mais de uma rota
repositories/ ← (ou daos/) consultas Prisma complexas — só quando justificável
models/ ← (ou entities/) tipos e schemas Zod compartilhados
middlewares/ ← autenticação base, logging, rate-limit, CORS
workers/ ← consumidores de fila (ver stack de backend)

Práticas inegociáveis

Estas valem mesmo no padrão mínimo de um arquivo:

  • Zod em toda entrada — sem exceção (princípio 7).
  • Autenticação antes de qualquer operação protegida — middleware base + checagem específica na rota.
  • Sem segredos no código; sem logar tokens, chaves de API ou payloads sensíveis.
  • Tipagem total ponta a ponta — any proibido (princípio 6).
  • Contrato OpenAPI sai do Zod — ver OpenAPI e Scalar.

Resultado esperado

Endpoints tipados, validados e autenticados. No menor número de arquivos possível para o que o domínio exige — nem menos (regras espalhadas), nem mais (camadas vazias).