Código limpo em Rust: escrevendo de forma elegante e eficiente

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

Por que código limpo em Rust não é um luxo, mas uma necessidade

\n\n

Rust é uma linguagem que exige disciplina do desenvolvedor. O compilador aqui é rigoroso, mas justo: ele não perdoa descuidos com memória, mas oferece em troca uma velocidade e segurança incríveis. No entanto, para realmente liberar o potencial do Rust, não basta apenas fazer o código compilar. É preciso escrever código limpo — compreensível, sustentável e elegante.

\n\n

Neste artigo, vamos explorar como escrever código limpo em Rust para que seu projeto não se transforme em um labirinto de blocos unsafe e genéricos confusos. Você aprenderá sobre princípios de nomenclatura, expressões idiomáticas de ownership, tratamento de erros e estruturação de código. Vamos lá!

\n\n

1. Nomenclatura: fale a língua do Rust

\n\n

A nomenclatura correta é metade do sucesso. Em Rust, existem convenções rigorosas, e violá-las é como um pano vermelho para um touro (especialmente em code review).

\n\n

Regras básicas

\n
    \n
  • snake_case para variáveis, funções, métodos e módulos.
  • \n
  • PascalCase para tipos (struct, enum, trait).
  • \n
  • SCREAMING_SNAKE_CASE para constantes e variáveis estáticas.
  • \n
\n\n

Exemplo:

\n\n
// Ruim\nlet UserName = "Alice";\nfn GetUserData() {}\nconst MAX_SIZE: u32 = 100;\n\n// Bom\nlet user_name = "Alice";\nfn get_user_data() {}\nconst MAX_SIZE: u32 = 100;
\n\n

Evite abreviações (a menos que sejam óbvias)

\n

Em vez de calc_avg(), é melhor escrever calculate_average(). Em vez de tmp, use temp_buffer. Rust incentiva a legibilidade, não a brevidade.

\n\n

Dica: se você estiver escrevendo uma função que recebe um closure, use os nomes f, g ou closure — esta é uma prática comum.

\n\n

2. Ownership e borrowing: seja amigo do compilador

\n\n

O sistema de ownership é o coração do Rust. O código limpo respeita as regras de ownership e borrowing, sem tentar contorná-las com clone() ou Rc desnecessariamente.

\n\n

Regra: prefira borrowing a ownership

\n

Se uma função não precisa assumir a ownership, aceite uma referência &T ou uma referência mutável &mut T.

\n\n
// Ruim: clone desnecessário\nfn process(data: Vec<i32>) {\n    let mut sum = 0;\n    for &val in &data {\n        sum += val;\n    }\n    println!("Sum: {}", sum);\n}\n\n// Bom: borrowing\nfn process(data: &[i32]) {\n    let mut sum = 0;\n    for &val in data {\n        sum += val;\n    }\n    println!("Sum: {}", sum);\n}
\n\n

Evite clonagem excessiva

\n

Se você precisar passar dados para vários lugares, use Rc (para cenários single-thread) ou Arc (para multi-thread). Mas não abuse: para casos simples, referências são suficientes.

\n\n

3. Tratamento de erros: abandone o pânico

\n\n

Em Rust, existem duas formas principais de tratar erros: panic! (erro irrecuperável) e Result<T, E> (recuperável). O código limpo usa Result sempre que possível. O pânico é o último recurso para situações truly excepcionais (como divisão por zero).

\n\n

Use o operador ?

\n

Esta é uma forma concisa de propagar o erro para cima. Em vez de match extensos, escreva:

\n\n
use std::fs::File;\nuse std::io::Read;\n\nfn read_file(path: &str) -> Result<String, std::io::Error> {\n    let mut file = File::open(path)?;\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?;\n    Ok(contents)\n}
\n\n

Crie seus próprios tipos de erro

\n

Em vez de usar String como erro, defina uma enumeração:

\n\n
#[derive(Debug)]\nenum MyError {\n    Io(std::io::Error),\n    Parse(std::num::ParseIntError),\n}\n\nimpl From<std::io::Error> for My                

Blogs

Book Recommendations