Requisitos para Especificações Técnicas
Solicitações de produto chegam como histórias de usuário; engenheiros entregam especificações técnicas - formas de API, modelos de dados, modos de falha e planos de implantação. Uma boa tradução evita "construir o botão" sem conhecer as regras de faturamento, idempotência ou os limites do serviço Rust.
Receita
Cartão de receita de referência rápida - pronto para copiar e colar.
# Especificação Técnica: <funcionalidade>
## Problema / resultado do usuário
## Escopo (dentro) / Não-objetivos (fora)
## Esboço da API (rotas Axum + tipos serde)
## Mudanças no modelo de dados (migrações sqlx expandir-contrair)
## Modos de falha e retentativas
## Observabilidade (spans de tracing, métricas)
## Implantação (flag, canary) e rollback
## Testes de aceitação (Dado/Quando/Então)
## Perguntas abertas e spikesQuando usar isso:
- Pontos de história excedem um sprint
- Impacto entre crates ou esquemas
- PM pede data antes que a engenharia entenda a forma
- Toque de conformidade ou segurança
Exemplo de Trabalho
# Especificação Técnica: Exportar faturas como PDF
## Problema
Usuários de finanças precisam de faturas em PDF em exportação em massa (até 500/requisição).
## Não-objetivos
- Entrega por e-mail (épico separado)
- Marca personalizada por tenant (fase 2)
## API
`POST /v1/invoices/export` → 202 + `job_id`
`GET /v1/jobs/{id}` → status + URL S3 quando pronto
## Dados
Ler `invoices` + `line_items`; sem mudança de esquema fase 1.
## Implementação (Rust)
- Rota Axum enfileira tarefa Tokio ou binário de worker separado
- Worker usa `printpdf` ou pipeline headless; faz upload via `aws-sdk-s3`
- Cabeçalho `Idempotency-Key` deduplica retentativas
## Modos de falha
- S3 indisponível → retentar com backoff; DLQ após 5 tentativas
- PDF > 50MB → falhar job com código de erro claro
## Aceitação
- Dado 10 faturas, Quando o job de exportação completar, Então a URL ZIP é válida por 24h
- p95 tempo do job < 60s para 100 faturas em teste de carga de staginguse serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize)]
pub struct ExportRequest {
pub invoice_ids: Vec<String>,
#[serde(default = "default_max")]
pub max_count: usize,
}
fn default_max() -> usize { 500 }
#[derive(Debug, Serialize)]
pub struct JobStatus {
pub job_id: String,
pub state: String, // pending | running | done | failed
pub download_url: Option<String>,
}O que isso demonstra:
- Resultado do usuário declarado sem prescrever soluções apenas de UI
- Padrão de job assíncrono escolhido explicitamente para a stack Rust
- Modos de falha e critérios de aceitação são testáveis
- Modelos Serde alinham PM e engenharia antecipadamente
Análise Detalhada
Como Funciona
- Perguntas de descoberta - Quem, frequência, conformidade, volume de pico, tolerância a falhas.
- Fatia vertical - Caminho fino de ponta a ponta antes de polir casos extremos.
- Contrato primeiro - Tipos Serde antes da implementação profunda.
- Disciplina de migração - Expandir-contrair chamado na especificação, não surpresa no PR.
- Revisão com PM - Percorrer os testes de aceitação; ajustar o escopo antes do commit do sprint.
Checklist de Qualidade da Especificação
| Seção | Ausente = risco |
|---|---|
| Não-objetivos | Aumento de escopo no meio do sprint |
| Rollback | Incidente sem mitigação |
| Observabilidade | Lançamento cego em produção |
| Idempotência | Cobranças/exportações duplicadas |
Armadilhas
- Especificação após o início do código - Retrabalho e culpa. Correção: Sem commit de sprint sem especificação revisada para trabalho médio+.
- Aceitação vaga - "Rápido" ou "escalável". Correção: Números: p95, máx. de linhas, códigos de erro.
- Ignorar tier do worker - Especificação de API sem história de fila. Correção: Seção de worker obrigatória para trabalho assíncrono.
- Conformidade oculta - PII em logs descoberto tarde. Correção: Classificação de dados no cabeçalho da especificação.
- Uma especificação gigante - Nunca é entregue. Correção: Não-objetivos da Fase 1 explícitos; ticket stub da fase 2.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| RFC para arquitetura | Debate entre equipes | História simples de CRUD |
| Sessão de mapeamento de histórias | Nova área de produto | Endpoint de API único |
| Spike de protótipo | UX de alta incerteza | Faturamento regulamentado sem especificação |
| Apenas OpenAPI | Consumidores de API externos | Fluxos de worker internos omitidos |
FAQs
Quanto tempo devem levar as especificações?
Meio dia a dois dias para funcionalidades médias; fazer spike se demorar mais de três dias para escrever.
Quem aprova as especificações?
Líder técnico + PM assinam a aceitação; segurança para PII/pagamento.
Especificação para correções de bugs?
Leve: repro, hipótese da causa raiz, plano de teste - pular o template completo.
Axum vs worker na especificação?
Indicar qual binário gerencia cada caminho e os limites dos crates compartilhados.
Como lidar com requisitos em mudança?
Alterar a versão da especificação; reestimar; não absorver escopo silenciosamente.
Especificações e Jira?
Vincular PR da especificação ou documento no épico; testes de aceitação copiados para o ticket.
Funcionalidades CLI em especificação?
Incluir UX do clap, códigos de saída e canal de distribuição (cargo-dist).
Quando envolver o design?
Antes do congelamento da API quando o UX ditar paginação, filtros ou limites de exportação.
Limite de perguntas abertas?
Se >3 bloqueadores, limitar spikes por tempo antes do commit do sprint.
Armazenamento de especificações?
docs/specs/ no repositório - versionado com o código.
Relacionados
- Estimativa e Risco - dimensionar após a especificação
- Contribuições para o Roadmap - alimentar o planejamento
- Executando Revisões de Design - grandes mudanças
- Roteamento Axum - padrões HTTP
- Serde - modelagem de contrato
Versões da Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.