Revisão de código em Rust: 5 observações que todo sênior fará

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que Rust é tão rigoroso e como o code review ajuda a não enlouquecer

\n

Você escreveu um código em Rust. Ele compilou — viva! Mas eis o problema: o desenvolvedor sênior, ao abrir seu Pull Request, suspira e começa a escrever comentários. Familiar? Rust é uma linguagem com uma filosofia única: ele confia em você, mas verifica tudo. No entanto, o compilador não vê o que o olho experiente vê. Ele não dirá: "Ei, isso pode ser feito de forma mais elegante" ou "Seu código está vazando — não memória, mas desempenho".

\n

Neste artigo, faremos uma revisão de código em Rust e analisaremos observações típicas de seniores. Você aprenderá como transformar "código apenas funcional" em algo idiomático e confiável. Vamos lá!

\n\n

1. Ignorar o sistema de tipos: "Vou colocar tudo em String"

\n

O erro mais comum de iniciantes é usar String ou tipos genéricos onde tipos específicos são necessários. O sênior dirá: "Seu tipo deve refletir a lógica de negócios, não ser apenas uma string".

\n

Problema: perda de semântica

\n

Imagine que você está escrevendo uma função para trabalhar com endereços de e-mail:

\n
fn send_email(to: String, subject: String, body: String) {\n    // ...\n}
\n

O que há de errado aqui? Você pode confundir to e subject — o compilador não perceberá. O sênior sugerirá usar o padrão newtype:

\n
struct Email(String);\nstruct Subject(String);\nstruct Body(String);\n\nfn send_email(to: Email, subject: Subject, body: Body) {\n    // ...\n}
\n

Parece excessivo? Em um code review Rust, essa abordagem é o padrão ouro. Ela torna o código autodocumentado e elimina toda uma classe de erros.

\n\n

2. Abuso de clone(): copiar não significa possuir

\n

Desenvolvedores juniores costumam usar .clone() em todos os lugares onde o compilador reclama de empréstimos. O sênior dirá: "Você está apenas desistindo diante do borrow checker. Pense diferente".

\n

Exemplo: clone desnecessário

\n
fn process(data: Vec<i32>) {\n    let first = data[0].clone();\n    let second = data[1].clone();\n    // ...\n}
\n

i32 implementa a trait Copy — clone() aqui é totalmente desnecessário. Mas o problema é mais profundo: se você clona estruturas grandes (como Vec ou String), terá um impacto no desempenho.

\n

A abordagem correta é trabalhar com referências:

\n
fn process(data: &[i32]) {\n    let first = &data[0];\n    let second = &data[1];\n    // ...\n}
\n

Em uma revisão de código em Rust, você deve explicar por que está clonando. Se a resposta for "para o compilador não reclamar" — prepare-se para um comentário arrasador.

\n\n

3. Tratamento de erros ruim: .unwrap() não é a solução final

\n

Seniores odeiam unwrap() e expect() em código de produção. Por quê? Porque transformam um erro potencialmente recuperável em pânico. E pânico em Rust é uma terminação abrupta.

\n

O que há de errado com este código?

\n
let file_content = std::fs::read_to_string("config.txt").unwrap();
\n

Se o arquivo não existir — o programa quebra. O sênior sugerirá:

\n
let file_content = std::fs::read_to_string("config.txt")\n    .map_err(|e| format!("Falha ao ler config: {}", e))?;
\n

Use o operador ? e tipos de erro próprios. Essa é a base do Rust idiomático. Em um code review Rust, esta é uma das primeiras observações.

\n\n

4. Desempenho esquecido: alocações e iteradores

\n

Rust é uma linguagem de sistema. O sênior olhará não apenas para a segurança, mas também para a velocidade. Um dos problemas típicos é criar coleções desnecessárias.

\n

Exemplo: colecionar sem necessidade

\n
let numbers: Vec<i32> = (0..100).collect();\nlet doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();                

Blogs

Book Recommendations