Software · Arquitetura de Software

Spec-Driven Development: Contratos Como Fonte Única da Verdade na Engenharia de Software

O que é Spec-Driven Development (SDD), como especificações formais guiam arquitetura, testes de contrato, geração de código e a orquestração determinística entre times e agentes de IA.

Diagrama conceitual de Spec-Driven Development ilustrando especificações formais como fonte da verdade entre contratos, testes e implementação
Neste artigo

Em boa parte das organizações de engenharia, a documentação técnica é tratada como um subproduto tardio: desenvolvedores escrevem controladores, modelam tabelas, sobem a aplicação e, se houver tempo hábil antes do deploy, executam geradores reflexivos para extrair um arquivo Swagger ou um diagrama retroativo. O resultado inevitável dessa abordagem é a degradação silenciosa dos contratos de comunicação, onde o código em produção diverge da expectativa dos clientes, gerando retrabalho contínuo, quebras acidentais de integração e dependência de reuniões síncronas de alinhamento.

O Spec-Driven Development (SDD), ou Desenvolvimento Orientado a Especificações, inverte radicalmente essa dinâmica. Sob essa metodologia, a especificação técnica formal — declarativa, versionada, estruturada e legível tanto por seres humanos quanto por compiladores e ferramentas automatizadas — é o primeiro artefato produzido, atuando como a fonte única da verdade (single source of truth) antes que qualquer linha de lógica de negócio seja codificada.

flowchart TD
  Spec["Especificação Formal Declarativa<br/>(OpenAPI / AsyncAPI / Protobuf / JSON Schema)"]

  subgraph PipelineValidacao["Fase 1: Governança & Prototipagem Imediata"]
    Lint["Linter de Contrato & Regras de Estilo<br/>(Spectral / Buf Lint)"]
    Mock["Servidores Mock Instantâneos<br/>(Prism / Microcks / MSW)"]
  end

  subgraph PipelineDerivacao["Fase 2: Automação & Validação"]
    Codegen["Geração de Código (Codegen)<br/>(Interfaces, DTOs e SDKs Tipados)"]
    ContractTests["Testes de Conformidade & Fuzzing<br/>(Schemathesis / Dredd / Pact)"]
  end

  subgraph Execucao["Fase 3: Implementação & Entrega"]
    DevFrontend["Frontend & Consumidores<br/>(Trabalham com Mocks em D0)"]
    DevBackend["Backend & Engenharia de Domínio<br/>(Implementa stubs garantidos pela Spec)"]
    Deploy["CI/CD Gate:<br/>Validação estrita de Breaking Changes"]
  end

  Spec --> Lint
  Spec --> Mock
  Spec --> Codegen
  Spec --> ContractTests

  Mock --> DevFrontend
  Codegen --> DevBackend
  ContractTests --> Deploy

O Ciclo de Vida do Spec-Driven Development

Diferente de um simples documento de requisitos textual em PDF ou Confluence, uma especificação no SDD é executável e computável. O fluxo de trabalho de uma equipe que adota SDD estrutura-se em cinco etapas contínuas:

1. Autoria e Desenho Colaborativo (Design Phase)

Antes de abrir a IDE para codificar uma API REST, um fluxo de mensageria com Apache Kafka ou uma comunicação gRPC, engenheiros de backend, arquitetos, desenvolvedores frontend e engenheiros de QA sentam para redigir o contrato.

  • Para APIs REST/HTTP: OpenAPI 3.1 define rotas, status codes RFC 7807, parâmetros e payloads JSON Schema.
  • Para Mensageria e Eventos: AsyncAPI padroniza canais, tópicos, envelopes e garantias de entrega.
  • Para RPC de alta performance: Protocol Buffers (proto3) especifica serviços, métodos e estruturas binárias.

2. Governança Estática e Linting de Contrato

Assim como o código-fonte passa por linters como ESLint, Roslyn ou SonarQube, a especificação é submetida a ferramentas de validação semântica (como Spectral ou buf). Regras organizacionais garantem consistência sem depender de opiniões individuais:

  • Todos os endpoints devem documentar respostas para erros 400, 401 e 500.
  • Paginações devem seguir obrigatoriamente o padrão de cursor ou offset padronizado pela empresa.
  • Nenhum campo pode expor dados sensíveis não ofuscados (em conformidade com LGPD/GDPR).

3. Paralelismo Total com Mocks em "Dia Zero" (Day-Zero Mocking)

Com a especificação validada e commitada no repositório de contratos, ferramentas como Prism ou MSW criam servidores mock dinâmicos em segundos. Equipes de frontend, aplicativos móveis e terceiros começam a construir e testar telas e jornadas inteiras no mesmo dia, sem precisar esperar que o time de backend termine de configurar bancos de dados ou persistência.

4. Geração Automática de Código (Codegen)

O contrato é consumido por geradores automáticos (OpenAPI Generator, Kiota, protoc):

  • O time de backend recebe interfaces de controladores fortemente tipadas e classes DTO prontas, precisando focar apenas na implementação das regras de negócio.
  • Os clientes consumidores recebem SDKs fortemente tipados (TypeScript, Kotlin, Swift, C#), eliminando requisições manuais com URLs literais em texto solto.

5. Testes Baseados em Propriedades e CI/CD Gate

Testes não precisam ser criados manualmente para cada parâmetro: motores como Schemathesis leem a especificação e disparam centenas de milhares de payloads maliciosos, valores de borda e variações de tipos (property-based fuzzing) contra a implementação real, provando matematicamente que o servidor nunca viola o contrato anunciado.


Matriz Comparativa: SDD vs TDD vs BDD vs Code-First

Para entender onde o Spec-Driven Development se situa no ecossistema de engenharia, vale contrastá-lo com as abordagens consolidadas de desenvolvimento:

Dimensão Code-First Tradicional TDD (Test-Driven Development) BDD (Behavior-Driven Development) SDD (Spec-Driven Development)
Ponto de Partida Código nos controladores/classes Teste unitário automatizado (Red-Green-Refactor) Cenários de comportamento em linguagem Gherkin Especificação formal computável do contrato
Foco Primário Rapidez imediata em protótipos Design interno e coesão de classes e funções Alinhamento com objetivos de negócio e usuários Contratos de integração e fronteiras de sistemas
Granularidade Linhas de código e métodos Funções individuais e classes Fluxos de telas e jornadas de usuário Serviços distribuídos, APIs, eventos e dados
Desbloqueio de Consumidores Tardio (apenas após deploy em staging) Nenhum (escopo interno do componente) Indireto (validação de regras) Imediato (mocks e SDKs gerados em D0)
Governança Manual, frágil e sujeita a drift Focada em cobertura de testes unitários Focada em critérios de aceite Automatizada por linters de contrato e CI Gates
Geração de Código Inversa (código gera spec reflexiva) Não se aplica Criação de esqueletos de passos de teste Direta (spec gera contratos, DTOs e clientes)

O SDD não substitui o TDD nem o BDD; ele os precede e potencializa. A especificação formal estabelece os limites do sistema; os cenários de BDD validam se os fluxos de negócio cumprem o propósito; e os ciclos de TDD guiam a escrita dos algoritmos internos que realizam a lógica da aplicação.


Governança Automatizada: O Papel dos Linters de Especificação

Um dos maiores riscos em arquiteturas de microsserviços é a divergência de dialetos: cada squad escolhe uma nomenclatura diferente para o identificador (userId vs id_usuario vs user_uuid) ou inventa formatos de erro caseiros.

No SDD, a governança é automatizada através de arquivos de regras como o Spectral (.spectral.yaml), executados diretamente no pipeline de pull requests:

extends: ["spectral:oas"]
rules:
  rfc7807-error-structure:
    description: "Todas as respostas 4xx e 5xx devem implementar o schema RFC 7807 (Problem Details)."
    given: "$.paths.*.*.responses[?(@property.match(/^(4|5)/))].content['application/json'].schema"
    severity: error
    then:
      field: "$ref"
      function: pattern
      functionOptions:
        match: "#/components/schemas/ProblemDetails"

  kebab-case-paths:
    description: "Todos os segmentos de rota de API devem usar kebab-case em letras minúsculas."
    given: "$.paths[*]~"
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: "^(/[a-z0-9]+(-[a-z0-9]+)*|/{[a-zA-Z0-9_-]+})+$"

Se um desenvolvedor enviar um PR contendo um endpoint /obterDadosUsuario retornando erro 400 em formato de string solta, o linter falha o check de CI antes que qualquer revisão humana seja necessária, preservando o tempo dos engenheiros sêniores para focar na arquitetura de negócio.


SDD na Era dos Agentes Autônomos e Engenharia com IA

Com a ascensão de assistentes de código e agentes autônomos de IA (como Claude Code, Gemini CLI, Cursor e sistemas multi-agente), o Spec-Driven Development deixou de ser apenas uma boa prática para se tornar um pré-requisito de confiabilidade.

Modelos de linguagem possuem uma limitação inerente: se você pedir "Crie uma API para processamento de pagamentos", a IA alucinará estruturas de dados plausíveis, mas completamente aleatórias em convenções, status codes e validações.

No modelo de Engenharia de Software Orientada por Especificações com IA:

flowchart LR
  Engenheiro["Arquiteto / Engenheiro"] -->|"Escreve ou Refina"| Spec["Spec Formal Estrita<br/>(Contratos, Invariantes e Constraints)"]
  Spec -->|"Prompt de Contexto Fechado"| AgenteIA["Agente Autônomo de Código"]
  AgenteIA -->|"Gera Implementação"| CodigoApp["Código da Aplicação"]
  CodigoApp -->|"Executa Bateria de Testes da Spec"| Verificador["Schemathesis / Test Runner"]
  Verificador -->|"Falhas de Conformidade"| AgenteIA
  Verificador -->|"100% Conforme"| PR["Pull Request Aprovado"]
  1. A Spec como Delimitador de Contexto: A especificação fornece à IA os limites exatos do problema: inputs válidos, tipos rigorosos, cenários de erro possíveis e restrições de infraestrutura.
  2. Avaliação Determinística de Resultados: O agente não conclui a tarefa quando "acha que acabou", mas sim quando a bateria de testes gerada a partir da spec atinge 100% de conformidade estática e dinâmica.
  3. Imunidade a Deriva Arquitetural: O código gerado pela IA pode ser reescrito ou descartado sem dó a qualquer momento, pois a inteligência estrutural do sistema permanece intacta na especificação.

Boas Práticas para Adoção em Produção

Para consolidar o Spec-Driven Development sem burocracia excessiva, três diretrizes operacionais são indispensáveis:

  1. Repositório Central de Contratos ou Git Submodules: Mantenha especificações em repositórios próprios com controle semântico de versões (semver). Mudanças incompatíveis (breaking changes) exigem bump de versão maior (v2), verificado automaticamente via ferramentas como oasdiff ou buf breaking.
  2. Nunca Edite o Código Gerado: Stubs e clientes de API gerados por codegen devem residir em diretórios isolados ou pacotes de biblioteca (NuGet, npm) e nunca receber edições manuais. A regra é rígida: altere a especificação, reexecute o gerador e implemente a extensão via injeção de dependência ou herança.
  3. Trate Specs como Código: Especificações exigem revisões de PR tão criteriosas quanto o código executável. Discussões de nomes de campos, unidades de medida e códigos de erro pertencem ao PR da especificação, onde mudar uma linha custa segundos, e não semanas após a persistência em banco.

Ao adotar o Spec-Driven Development, equipes de engenharia substituem a incerteza do código reativo pela solidez de sistemas construídos sobre contratos inquebráveis, viabilizando arquiteturas desacopladas, times autônomos e integração confiável com a nova geração de ferramentas de inteligência artificial.

Explorar este tema no Grafo de Conhecimento