Padrões Anti-Comuns
Reconheça os anti-padrões do Rust cedo: eles compilam, mas criam panics, dívida de performance ou grafos inadministráveis.
Receita
// Anti-padrão
let data = fetch().unwrap().clone().clone();
// Prefira
let data = fetch().context("fetch")?;
process(&data);Quando usar isso: Revisão de código, limpeza com clippy e refatorações pós-incidente.
Exemplo de Trabalho
| Anti-padrão | Problema | Correção |
|---|---|---|
unwrap() em biblioteca | panic para chamadores | ? + erros tipados |
clone() para agradar o borrow checker | custo oculto | reestruturar propriedade, Arc, ou lifetimes |
Grafo Rc<RefCell<T>> | panics de borrow em tempo de execução | arena, índices, ou propriedade única |
String em tudo | alocações | &str, Cow, Arc<str> |
async fn bloqueando | runtime travado | spawn_blocking |
dyn Error em tudo | apagamento, sem contexto | enums de erro concretos + thiserror |
O que isso demonstra:
- Anti-padrões frequentemente começam como correções rápidas
- Clippy sinaliza muitos (
unwrap_used,redundant_clone) - Bibliotecas não devem entrar em pânico com entradas inválidas
- Meça clones em caminhos críticos (hot paths)
Mergulho Profundo
APIs Stringly Typed (Tipadas por String)
Use newtypes e enums em vez de códigos de status String. Use unwrap em testes e protótipos apenas com o plano de removê-lo.
Anti-Padrões Async
std::thread::sleep em async, block_on dentro de um runtime, spawn sem limites e sem backpressure.
Armadilhas (Gotchas)
- Banir
clonecompletamente - às vezes correto na fronteira. Correção: clone uma vez no spawn, não por iteração. expectsem mensagem - panics opacos em produção. Correção:expect("invariante: ...")ouResult.- Excesso de
Arc- tudo compartilhado e mutável. Correção: passagem de mensagens entre tarefas. - Tipos de erro copiados e colados - mapeamento inconsistente. Correção: crate de erro compartilhado (workspace).
- Ignorar clippy em testes - maus hábitos se espalham. Correção: permitir restritivamente apenas em módulos de teste.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
Operador ? | Operações falíveis | Invariante verdadeiramente impossível (documentar) |
| Typestate | Estados ilegais | Booleano trivial de dois estados |
| Canais (Channels) | Isolamento de tarefas | Loop síncrono crítico (hot loop) |
FAQs
unwrap em main?
Aceitável para falha fatal de bootstrap por má configuração com mensagem.
clone em async spawn?
Frequentemente necessário para 'static; clone uma vez antes do spawn.
Rc em GUI?
UI de thread única pode usar Rc; ainda prefira propriedade clara.
todo! em produção?
Nunca em caminhos alcançáveis; use Err ou feature gate.
collect e depois iterar?
Alocação extra; encadeie iteradores se possível.
Box service?
OK na fronteira; injete genéricos no domínio principal.
mutex em lazy_static?
Padrão legado; prefira OnceLock/LazyLock.
serde Value em tudo?
Perde segurança de tipo; parseie em structs cedo.
threads raw?
Prefira tarefas tokio em apps async; threads para pools de CPU.
como impor?
clippy deny em CI, checklist de revisão, testes de arquitetura.
Relacionados
- Evitando Clones
- Panic vs Erros Recuperáveis
- Combatendo o Borrow Checker
- Melhores Práticas de Padrões Rust
Versões da Pilha: 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+.