Spec-first-dev
DDD para nomear as coisas, BDD para especificá-las, a menor mudança para satisfazê-las, evidência para provar. Independente de tecnologia.
1. Pensar antes de codificar
- Declare suposições. Se o pedido não for claro ou tiver várias interpretações, nomeie-as e pergunte. Nunca escolha silenciosamente.
- Se existir uma abordagem mais simples, diga e conteste.
- Leia o código que a tarefa afeta. Liste tudo o que a mudança deve alcançar (chamadores, testes, fixtures, configuração, exports) e o que ela pode quebrar (dados destruídos ou expostos, chamadores que param de funcionar). Isso é o escopo; funcionalidades extras não estão incluídas. Nomeie os extras ignorados em uma linha.
- Antes da primeira escrita, crie um branch a partir de main com um nome que se ajuste ao trabalho (ex:
feat/<funcionalidade>,fix/<bug>). Trabalho somente leitura não precisa de branch.
2. Modelar o domínio (DDD)
Antes de codificar, escreva em poucas linhas:
- Contexto delimitado e sua linguagem ubíqua: os termos que os especialistas do domínio usam. Reutilize os termos existentes do código; adicione novos apenas quando necessário.
- Agregado e seus invariantes: o que deve ser sempre verdade.
- Nomes em código, testes e mensagens usam esses termos. Rejeite nomes genéricos (
handle,process,manager,utils). - A lógica de domínio é pura sobre dados simples. I/O (banco de dados, rede, relógio, aleatoriedade) fica atrás de uma porta na borda, injetada.
Salve em docs/specs/<funcionalidade>.md.
Ignore esta etapa para mudanças triviais que não adicionam nenhum conceito de domínio.
3. Especificar comportamento (BDD)
Escreva cenários Dado/Quando/Então na linguagem do domínio, um por comportamento, incluindo os casos de borda e falha. Cada um descreve comportamento observável, não implementação. Obtenha a aprovação do usuário para cenários não óbvios; eles são o contrato. Salve-os em docs/features/<funcionalidade>.feature.
4. Planejar
Para trabalho de várias etapas, escreva um plano curto em docs/plans/<funcionalidade>.md: cada etapa com sua verificação. Ao continuar de uma especificação existente, ainda escreva o plano primeiro. Depois pare e peça ao usuário para revisá-lo; nunca execute até que ele aprove. Escolha a primeira opção que funciona completamente:
- Precisa existir? Se não, pule.
- Já existe neste código? Use como o código ao redor faz.
- Biblioteca padrão ou funcionalidade da plataforma? Use.
- Dependência instalada? Use. Nunca adicione uma por algumas linhas.
- Uma linha que um leitor entende de relance? Use.
- Caso contrário, o mínimo código que funciona.
5. Executar
Orquestração
Sempre que estiver prestes a executar tarefas, com ou sem especificação ou plano, verifique se elas se encaixam: vários itens separáveis (ex: 3+ correções), etapas independentes ou etapas de dificuldade claramente diferente. Se sim, leia orchestration.md (ao lado deste arquivo) e pergunte suas duas opções (via AskUserQuestion) antes da primeira edição: no mesmo turno da revisão do plano se você escreveu um plano, caso contrário imediatamente. Pergunte sempre; nenhuma outra aprovação (plano, especificação, "ok") conta como escolha. Se as tarefas não se encaixam, faça inline.
Vermelho, verde, refatorar, por cenário
- Transforme um cenário em um teste falho. Execute-o; veja-o falhar pelo motivo certo.
- Escreva o menor código que passa. Execute-o.
- Refatore apenas o que esta mudança tornou bagunçado.
- Correção de bug: reproduza com um cenário falho primeiro, use grep em todos os chamadores da função, corrija a causa raiz uma vez no código compartilhado.
6. Manter o diff cirúrgico
- Toque apenas no que for necessário. Corresponda ao estilo existente; não melhore código adjacente. Cada linha alterada remonta ao pedido.
- Remova apenas órfãos que sua mudança criou; mencione outro código morto, não o delete.
- Nenhuma abstração, wrapper, opção, configuração ou código "para depois" que ninguém pediu. Exclusão supera adição.
- Código que você move mantém seu tratamento de erro e validação.
- Comente apenas o porquê, em uma linha. Um limite conhecido recebe
atalho: <o limite>, <quando atualizar>. - Nunca corte: validação em limites de confiança, tratamento de erro que previne perda de dados, segurança, acessibilidade, qualquer coisa que o usuário pediu.
7. Verificar antes de declarar como pronto
Execute os testes e qualquer verificação de build ou tipo. Leia a saída. Relate resultados reais; se algo falhou ou não foi executado, diga. Nada de "deve funcionar".
8. Responder
Termine com uma ou duas linhas: o que você ignorou ou não verificou, e qualquer risco que o usuário precisa saber.