Código limpio en Rust: principios y ejemplos para principiantes

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Clean Code en Rust: principios y ejemplos



Escribir código limpio no es solo seguir tendencias de moda, sino una habilidad fundamental que distingue a un profesional de un aficionado. En el mundo de la programación de sistemas, donde Rust está ganando cada vez más popularidad, la capacidad de escribir código comprensible, mantenible y seguro se vuelve críticamente importante. En este artículo, analizaremos los principios principales de Clean Code aplicados a Rust, respaldándolos con ejemplos prácticos.



1. Nomenclatura: di lo que hace la variable



Una nomenclatura adecuada es la base de un código legible. En Rust, donde el tipado estricto y la propiedad (ownership) ya proporcionan mucha información, los buenos nombres hacen que el código sea autodocumentado.



Mal ejemplo:

fn calc(x: &[i32]) -> i32 {    let mut r = 0;    for i in x {        r += i;    }    r}


Buen ejemplo (Clean Code):

fn calculate_sum(numbers: &[i32]) -> i32 {    let mut total = 0;    for number in numbers {        total += number;    }    total}


Usa verbos para funciones (calculate, fetch, validate) y sustantivos para variables (total, user_name, config). Evita abreviaciones como tmp, res o val — no dicen nada sobre su propósito.



2. Funciones: pequeñas y con una sola responsabilidad



El principio de responsabilidad única (Single Responsibility) se aplica no solo a las clases, sino también a las funciones. Cada función debe hacer exactamente una cosa y hacerla bien.



Mal ejemplo (la función hace demasiado):

fn process_user_data(user: &User) -> Result<(), String> {    // Validación    if user.name.is_empty() {        return Err("Name is empty".to_string());    }    // Registro    println!("Processing user: {}", user.name);    // Guardar en BD    save_to_database(user)?;    // Enviar email    send_welcome_email(user.email)?;    Ok(())}


Buen ejemplo (división en funciones pequeñas):

fn process_user_data(user: &User) -> Result<(), AppError> {    validate_user(user)?;    log_user_processing(user);    save_user_to_db(user)?;    send_welcome_email(&user.email)?;    Ok(())}

fn validate_user(user: &User) -> Result<(), AppError> { if user.name.is_empty() { return Err(AppError::Validation("Name is required".into())); } Ok(())}

fn log_user_processing(user: &User) { println!("Processing user: {}", user.name);}


Observa: cada función ahora tiene una responsabilidad clara, y el código es más fácil de probar y modificar.



3. Manejo de errores: usa Result y tus propios tipos de error



En Rust no hay excepciones, y eso es excelente. Clean Code en Rust significa trabajar explícitamente con errores a través de los tipos Result<T, E> y Option<T>. Evita el pánico (unwrap(), expect()) en código de producción.



Mal ejemplo (pánico ante un error):

fn read_config(path: &str) -> Config {    let content = std::fs::read_to_string(path).unwrap();    serde_json::from_str(&content).unwrap()}


Buen ejemplo (manejo limpio de errores):

#[derive(Debug, thiserror::Error)]pub enum ConfigError {    #[error("Failed to read file: {0}")]    IoError(#[from] std::io::Error),    #[error("Failed to parse config: {0}")]    ParseError(#[from] serde_json::Error),}

fn read_config(path: &str) -> Result<Config, ConfigError> { let content = std::fs::read_to_string(path)?; let config: Config = serde_json::fr

Blogs

Book Recommendations