Code propre en Rust : principes et exemples pour débutants

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Clean Code sur Rust : principes et exemples



Écrire du code propre n'est pas simplement suivre les tendances à la mode, mais une compétence fondamentale qui distingue un professionnel d'un amateur. Dans le monde de la programmation système, où Rust gagne de plus en plus en popularité, la capacité à écrire un code compréhensible, maintenable et sûr devient cruciale. Dans cet article, nous allons analyser les principes de base du Clean Code appliqués à Rust, en les appuyant par des exemples pratiques.



1. Nommage : dites ce que fait la variable



Un bon nommage est la base d'un code lisible. En Rust, où le typage strict et l'ownership (possession) fournissent déjà beaucoup d'informations, de bons noms rendent le code auto-documenté.



Mauvais exemple :

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


Bon exemple (Clean Code) :

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


Utilisez des verbes pour les fonctions (calculate, fetch, validate) et des noms pour les variables (total, user_name, config). Évitez les abréviations comme tmp, res ou val — elles ne disent rien sur leur objectif.



2. Fonctions : petites et avec une seule responsabilité



Le principe de responsabilité unique (Single Responsibility) ne s'applique pas seulement aux classes, mais aussi aux fonctions. Chaque fonction doit faire exactement une chose et la faire bien.



Mauvais exemple (la fonction fait trop de choses) :

fn process_user_data(user: &User) -> Result<(), String> {    // Validation    if user.name.is_empty() {        return Err("Name is empty".to_string());    }    // Journalisation    println!("Processing user: {}", user.name);    // Sauvegarde en base de données    save_to_database(user)?;    // Envoi d'email    send_welcome_email(user.email)?;    Ok(())}


Bon exemple (division en petites fonctions) :

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);}


Remarquez : chaque fonction a désormais une responsabilité claire, et le code est devenu plus facile à tester et à modifier.



3. Gestion des erreurs : utilisez Result et vos propres types d'erreurs



En Rust, il n'y a pas d'exceptions, et c'est parfait. Le Clean Code en Rust signifie un travail explicite avec les erreurs via les types Result<T, E> et Option<T>. Évitez les paniques (unwrap(), expect()) dans le code de production.



Mauvais exemple (panique en cas d'erreur) :

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


Bon exemple (gestion propre des erreurs) :

#[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