Entrevista Série AI 16: Como deve ser um bom Spec Coding?
Um bom Spec Coding (Programação Orientada por Especificações) tem como núcleo transformar "ideias vagas" em "contratos precisos, verificáveis e executáveis". Não se trata apenas de escrever um documento, mas de estabelecer uma linguagem de comunicação inequívoca entre humanos e AI (ou entre humanos). A seguir, apresento as características de um bom spec a partir de quatro dimensões: estrutura de conteúdo da especificação, princípios de escrita, fluxo de colaboração com AI e verificação de qualidade.
1. Estrutura padrão de um documento de especificação (exemplo com módulo funcional)
| Seção | Conteúdo obrigatório | Exemplo |
|---|---|---|
| 1. Objetivo e Escopo | Descrever em uma frase o que fazer e claramente o que não fazer | "Implementar API de registo de utilizador, sem incluir verificação de email" |
| 2. Contrato de Entrada/Saída | Estrutura de dados, tipos, campos obrigatórios/opcionais, valores de exemplo | Corpo do pedido POST /register {email: string, password: string}, resposta 201 ou 400 com código de erro |
| 3. Comportamento e Lógica | Regras de negócio, condições de fronteira, transições de estado | "A password deve ter 8-20 caracteres, incluindo pelo menos um número; se o email já existir, retornar 409" |
| 4. Tratamento de Erros | Todos os cenários de exceção possíveis e respetivos códigos/mensagens de erro | "Falha de conexão à base de dados → retornar 503, não expor stacktrace" |
| 5. Requisitos Não Funcionais | Desempenho (tempo de resposta < 200ms), segurança (consultas parametrizadas), logs, observabilidade | "Todas as SQL devem usar pré-compilação; registar email mas não registar password" |
| 6. Casos de Teste (cruciais) | Pelo menos 3 entradas típicas + 2 entradas de fronteira/exceção, com saídas esperadas | Ver tabela abaixo |
| 7. Dependências e Restrições | Bibliotecas, versões, variáveis de ambiente | "Python 3.10+, FastAPI, variável de ambiente DB_URL" |
Exemplo de casos de teste (incorporados no spec)
| Cenário | Entrada | Saída Esperada |
|---|---|---|
| Registo normal | email: a@b.com, pwd: Pass1234 |
201, retornar user_id |
| Password demasiado curta | pwd: Ab1 |
400, código de erro WEAK_PASSWORD |
| Email já existe | mesmo email acima | 409, código de erro EMAIL_EXISTS |
Um bom Spec deve primeiro escrever os casos de teste, pois a AI pode gerar testes unitários diretamente a partir deles e, após a conclusão, verificar automaticamente.
2. Princípios fundamentais para escrever Spec (variante SMART)
| Princípio | Explicação | Contraexemplo |
|---|---|---|
| Preciso (Precise) | Usar números concretos, tipos, condições booleanas; evitar "possivelmente", "geralmente" | ❌ "A password deve ser suficientemente segura" → ✅ "A password deve ter pelo menos 8 caracteres, incluindo maiúsculas, minúsculas e números" |
| Verificável (Verifiable) | Cada requisito deve poder ser avaliado como aprovado/reprovado por teste automático ou inspeção manual | ❌ "O código deve ser elegante" → ✅ "Complexidade ciclomática da função ≤ 10, sem blocos de código duplicados" |
| Inequívoco (Unambiguous) | O mesmo termo deve ter o mesmo significado em todo o texto; fornecer glossário se necessário | ❌ "Se o utilizador não existir, retornar erro" → ✅ "Utilizador não existe → retornar 404 com {code: 'USER_NOT_FOUND'}" |
| Completo (Complete) | Cobrir caminho feliz, todos os caminhos de exceção e requisitos não funcionais | ❌ Apenas escrever cenário de sucesso → ✅ Incluir timeout de base de dados, permissões insuficientes, etc. |
| Atómico (Atomic) | Um spec descreve apenas um ponto funcional que pode ser entregue de forma independente (facilita a AI completar de uma vez) | ❌ Usar um spec para escrever "todo o sistema de pagamento" → ✅ Dividir em "gerar ordem de pagamento", "verificar assinatura de callback", "reembolso" |
3. Fluxo de Spec Coding na colaboração com AI
- Humano escreve o spec (estrutura acima, especialmente casos de teste e assinaturas de funções).
- Alimentar o spec de uma vez à AI (não adicionar requisitos de forma dialogal, para evitar poluição de vibração).
- AI produz código + testes unitários (a AI deve gerar testes executáveis de acordo com os casos de teste no spec).
- Executar os testes: se todos passarem, prosseguir; se não, modificar o spec ou corrigir diretamente o código (pode entrar num pequeno ciclo, mas registar as alterações).
- Revisão humana: verificar se há funcionalidades fora do spec (scope creep) e questões de segurança/desempenho.
- Consolidar: submeter o documento spec e o código final juntos no repositório como documentação permanente.
Prática chave: Spec como código — usar
spec.md+test_spec.py, onde o ficheiro de teste provém diretamente dos exemplos do spec, de modo que futuras modificações no código apenas exijam executar os testes para verificar se o spec foi quebrado.
4. Efeitos de um bom Spec (podem servir como critérios de aceitação)
- Determinismo: o mesmo spec produz implementações semelhantes quando dado a diferentes AIs (ou pessoas).
- Testabilidade: após escrever o código, é possível verificar automaticamente 90% da correção.
- Manutenibilidade: passados seis meses, qualquer pessoa que leia o spec consegue entender a intenção do design original.
- Baixo custo de comunicação: a equipa discute apenas o spec, não as linhas de código específicas.
- Segurança/qualidade integradas: requisitos de segurança (como consultas parametrizadas) e condições de fronteira são escritos no spec, e a AI deve cumpri-los.
5. Exemplo de um bom Spec (versão minimalista)
# Spec: API de Registo de Utilizador
## Escopo
- Receber email, password
- Não enviar email de verificação, não verificar autenticidade do email
## Contrato
POST /register
Content-Type: application/json
Request: { "email": string, "password": string }
Response 201: { "user_id": string }
Response 400: { "code": "INVALID_PASSWORD" | "INVALID_EMAIL" }
Response 409: { "code": "EMAIL_ALREADY_EXISTS" }
## Comportamento
- email deve estar em formato básico RFC 5322 (ex: a@b.c)
- password: comprimento 8-20, pelo menos um número e uma letra maiúscula
- Armazenar usando bcrypt com custo de salt 10
- Se antes de guardar na base de dados se detetar que o email já existe → 409
## Casos de Teste (entrada -> código de estado esperado + campos da resposta)
| Input email | password | Esperado |
|------------|----------|------|
| test@x.com | Pass1234 | 201, user_id existe |
| test@x.com | pass | 400, INVALID_PASSWORD |
| bad | Pass1234 | 400, INVALID_EMAIL |
| (email já existente) | Pass1234 | 409, EMAIL_ALREADY_EXISTS |
## Não Funcional
- SQL deve usar consultas parametrizadas (para prevenção de injeção)
- Registar IP de origem do pedido, não registar password
- Tempo de resposta: 95% dos pedidos < 100ms (excluindo bcrypt)
## Dependências
- Python 3.10+, FastAPI, bcrypt, asyncpg
Bom Spec Coding = transformar as "decisões de design" humanas em "casos de teste + assinaturas de tipo + restrições de comportamento" da máquina, deixando a AI apenas preencher a implementação, enquanto o humano mantém sempre o controlo da qualidade e direção.
评论
暂无已展示的评论。
发表评论(匿名)