Habilidade de Propor Design de Funcionalidade
Propósito
Criar um documento de design técnico que orienta a implementação. Ele fornece arquitetura, padrões e decisões de design sem escrever o código real.
Quando Usar
- O conceito da funcionalidade e os requisitos existem
- Pronto para planejar a abordagem de implementação
- Necessidade de documentar arquitetura e padrões de design
Pré-requisitos
- O conceito da funcionalidade existe em
docs/features/NNNN-nome-da-funcionalidade/concept.md - Os requisitos existem em
docs/features/NNNN-nome-da-funcionalidade/requirements.md - O usuário entende a abordagem técnica
Procedimento
1. Verificar se os Pré-requisitos Existem
# Verificar se o conceito e os requisitos existem
ls ./docs/features/NNNN-nome-da-funcionalidade/concept.md
ls ./docs/features/NNNN-nome-da-funcionalidade/requirements.md
Se algum não existir, conclua essas etapas primeiro.
2. Verificar Documento de Refinamento de Ideia
ls ./planning/NNNN-nome-da-funcionalidade/idea-honing.md 2>/dev/null
Se existir, revise-o para obter insights de design e considerações técnicas discutidas durante o refinamento.
3. Copiar Template de Design
cp ./docs/features/0000-templates/design.md ./docs/features/NNNN-nome-da-funcionalidade/
4. Preencher a Visão Geral
Escreva uma descrição de alto nível da arquitetura e da abordagem de design. Faça referência ao conceito e aos requisitos.
5. Identificar Restrições Críticas
Para cada operação chave, pergunte:
- Qual seria uma forma ERRADA de implementar isso?
- Quais características de desempenho são necessárias?
- Quais invariantes devem ser mantidas?
Preencha a tabela de Restrições Críticas com:
- ID: CC-1, CC-2, etc.
- Restrição: O que DEVE ser feito de uma forma específica
- Justificativa: Porquê (desempenho, correção, segurança)
- Antipadrão: A abordagem errada a ser rejeitada na revisão
Esta é a seção mais importante para evitar erros de implementação. Seja específico — restrições vagas não ajudam.
6. Definir Arquitetura
Descreva a estrutura geral:
- Relacionamentos entre componentes
- Fluxo de dados
- Responsabilidades das camadas
- Pontos de integração
Use diagramas simples com arte ASCII se for útil.
7. Explicar a Mecânica da Solução
Esta seção faz a ponte entre o "porquê" (conceito) e o "como" (arquitetura). Para cada desafio central identificado no conceito, explique como o design o aborda.
Para cada desafio, responda:
- Qual é o problema fundamental? (de
concept.md) - Qual elemento arquitetural o aborda?
- Por que essa abordagem funciona?
- O que falharia se fizéssemos de forma diferente?
Formate como uma tabela ou lista estruturada:
| Desafio | Elemento Arquitetural | Por que Funciona |
|---|---|---|
| Desafio do conceito | Componente/padrão que o aborda | Explicação do mecanismo |
Perguntas para ajudar os autores:
- "Se alguém perguntar 'como isso resolve X?', você consegue apontar para um componente específico?"
- "Um novo engenheiro entenderia por que este design foi escolhido em vez de alternativas?"
- "Cada componente principal tem uma razão clara para existir, ligada a um problema?"
Esta seção deve fazer com que os revisores confiem que o design realmente resolve os problemas declarados, não apenas descreve uma estrutura de código plausível.
8. Definir Modelo de Domínio
Especifique os tipos e operações principais:
Tipos
- Propósito e papel
- Propriedades principais
- Regras de validação
- Relacionamentos com outros tipos
Operações
- Assinaturas de funções (conceituais)
- O que fazem
- Comportamentos principais
- Invariantes (o que deve ser sempre verdadeiro)
9. Definir Estrutura de Módulos
Mostre como o código deve ser organizado:
- Estrutura de diretórios
- Responsabilidades dos módulos
- Organização de arquivos
- Separação de preocupações
Limite de tamanho de módulo: Este projeto impõe um limite de 550 linhas por módulo (veja scripts/lint_loc.py).
Ao projetar módulos, considere se um componente pode exceder esse limite.
Se sim, planeje a decomposição interna antecipadamente — divida por capacidade (ex.: builder.rs, searcher.rs), não por tipo de artefato.
A saída do linter inclui orientação de refatoração se os limites forem excedidos.
Mantenha impl blocks juntos: Todos os blocos impl para um tipo devem estar em um único arquivo.
Espalhar impl blocks entre arquivos dificulta que leitores (e IA) tenham uma visão completa do que um tipo faz.
Se a implementação de um tipo for muito grande, delegue para funções auxiliares ou tipos de componentes internos, em vez de dividir o próprio impl block.
// ✅ Bom: um único impl block delega para auxiliares
impl KnowledgeIndex {
pub fn build(&self, path: &Path) -> Result<()> {
self.builder.build(path) // delega para componente interno
}
}
// ❌ Ruim: impl blocks divididos entre arquivos
// facade/mod.rs: impl KnowledgeIndex { fn new() ... }
// facade/build.rs: impl KnowledgeIndex { fn build() ... }
// facade/search.rs: impl KnowledgeIndex { fn search() ... }
10. Documentar Padrões de Design
Descreva padrões relevantes e por que se aplicam:
- Quais padrões usar
- Como se encaixam no problema
- Orientação de implementação
11. Documentar Decisões de Design
Para escolhas significativas entre alternativas, adicione entradas na seção de Decisões de Design:
- O que foi decidido
- Quais alternativas foram consideradas
- Por que esta opção foi escolhida
- O que implica para a implementação
Isso cria um registro que ajuda implementadores a entender o raciocínio.
12. Adicionar Orientação de Implementação
Considerações principais para implementadores:
- Faça referência às Restrições Críticas por ID
- Considerações de desempenho
- Abordagem de teste
- Casos de borda a serem tratados
13. Manter o Código Mínimo
Lembre-se:
- Use código ilustrativo mínimo
- Foque em arquitetura e decisões
- Oriente implementadores, não implemente
- Faça referência a requisitos por ID quando relevante
Validação
Verifique o documento de design:
# Verificar se o arquivo existe
ls ./docs/features/NNNN-nome-da-funcionalidade/design.md
# Verificar se tem conteúdo
head -50 ./docs/features/NNNN-nome-da-funcionalidade/design.md
Problemas Comuns
Código demais: Se houver grandes blocos de código, remova-os e foque na orientação.
Muito abstrato: Se o design for vago, adicione nomes de tipos concretos e estrutura de módulos.
Arquitetura ausente: Certifique-se de que a estrutura geral está clara antes de se aprofundar em detalhes.
Não referenciar requisitos: Vincule as decisões de design de volta a IDs específicos de requisitos.
Mecânica da solução ausente: Se o design descreve estrutura, mas não por que resolve o problema, adicione a seção de Mecânica da Solução mapeando desafios para elementos arquiteturais.
Próximos Passos
Após criar o design:
- Revise com implementadores para verificar viabilidade
- Refine com base no feedback
- Uma vez que o design esteja sólido, crie o plano de teste usando a habilidade
propose-feature-test-plan - Em seguida, crie o plano de implementação usando a habilidade
propose-implementation-plan