Code Review em Rust: o que verificar e como dar feedback — guia para iniciantes
Code review (revisão de código) é o processo de verificar o código de outra pessoa antes de mesclá-lo ao branch principal do projeto. Para a linguagem Rust, conhecida por seu sistema de tipos rigoroso, segurança de memória e modelo único de ownership (propriedade), o code review adquire um significado especial. Desenvolvedores iniciantes frequentemente enfrentam dificuldades: como saber se o código foi escrito "à moda Rust"? Como não ofender o autor ao apontar erros? Neste artigo, abordaremos os principais aspectos da revisão para Rust, mostraremos exemplos e daremos dicas práticas.
1. Princípios básicos do code review em Rust
Antes de nos aprofundarmos nos detalhes técnicos, é importante entender a filosofia da revisão. Seu objetivo não é encontrar todas as falhas, mas ajudar um colega (ou a si mesmo) a escrever código de qualidade e sustentável. Em Rust, isso é especialmente importante devido às regras rigorosas do borrow checker e do sistema de ownership.
Aqui está o que verificar em primeiro lugar:
- Correção no gerenciamento de memória — mesmo que o código compile, podem existir erros lógicos.
- Conformidade com as expressões idiomáticas do Rust — uso de
Option,Result, traits em vez de herança. - Legibilidade e documentação — comentários, nomenclatura de variáveis, estrutura dos módulos.
- Desempenho — evitar clonagens e alocações desnecessárias.
É importante que revisores iniciantes lembrem: você não precisa saber tudo. Se algo não estiver claro, pergunte. Isso é normal.
2. O que verificar no código Rust: checklist para iniciantes
Vamos analisar pontos específicos aos quais prestar atenção ao revisar código Rust.
2.1. Trabalho com ownership e borrowing
Rust é a única linguagem popular onde os conceitos de ownership, borrowing e lifetimes estão incorporados ao compilador. No entanto, a revisão pode revelar problemas que o compilador não vê:
- Clonagem excessiva. Se o autor usa
.clone()em todos os lugares onde uma referência seria suficiente, isso é uma má prática. Exemplo:
// Ruim: clonagem desnecessáriafn process(data: Vec<i32>) { let cloned = data.clone(); // ... usamos cloned}
// Bom: passamos uma referênciafn process(data: &Vec<i32>) { // ... usamos &data}- Uso incorreto de lifetimes. Se o código contém anotações explícitas
'a, verifique se elas são realmente necessárias. Frequentemente, podem ser omitidas graças à elisão (lifetime elision). - Vazamentos de memória via
RcouArc. Verifique se não há referências cíclicas (paraRc, useWeak).
2.2. Tratamento de erros
Rust incentiva o tratamento explícito de erros através de Result e Option. Ao revisar, preste atenção em:
Resultnão utilizado. Se uma função retornaResult, mas o resultado é ignorado, isso é um problema potencial. Uselet _ = ...ou o método.ok().- Abuso de
unwrap(). Em código de produção,unwrap()eexpect()devem ser justificados. É melhor usar o tratamento viamatchou o operador?.
// Ruim: pode causar pânicolet value = some_result.unwrap();
// Bom: tratamento de errolet value = match some_result { Ok(v) => v, Err(e) => { eprintln!("Erro: {}", e); return; }};2.3. Uso de traits e programação genérica
Rust não suporta herança — em vez disso, usa traits