Quand un seul fichier devient trop étroit
\n\nVous codez en Rust. Votre projet grandit. Hier encore, main.rs contenait tout — fonctions, structures, quelques configurations. Et aujourd'hui, vous passez cinq minutes à trouver une fonction parmi des milliers de lignes. Cela vous dit quelque chose ?
Tôt ou tard, chaque développeur Rust doit diviser le code en parties logiques. Cela semble simple, non ? Créez un dossier, répartissez les fichiers, importez — et le tour est joué. Mais le système modulaire de Rust est réputé pour sa rigueur. Une seule erreur dans mod.rs — et le compilateur affiche une erreur que vous passerez une demi-heure à déchiffrer.
Dans cet article, nous analyserons les principales erreurs lors de la division d'un module Rust en plusieurs fichiers et, surtout, nous montrerons comment les éviter. Vous apprendrez à organiser correctement la structure des fichiers, quand utiliser mod.rs et quand utiliser lib.rs, et pourquoi pub use est votre meilleur ami.
Anatomie du système modulaire de Rust
\n\nAvant de plonger dans les erreurs, rappelons les bases. En Rust, un module est une unité d'organisation du code. Par défaut, chaque fichier est un module, mais ce n'est pas si linéaire.
\n\nIl existe deux approches :
\n\n- \n
- Fichier-module homonyme : le fichier
utils.rsdevient automatiquement le moduleutilssi vous déclarezmod utils;danslib.rsoumain.rs. \n - Répertoire-module : le dossier
utils/avec un fichiermod.rsà l'intérieur. Dans ce cas,mod.rsest le point d'entrée du module. \n
Cela semble simple, mais c'est là que se cache la plupart des pièges. Analysons les plus courants.
\n\nTop 5 des erreurs lors de la division d'un module en plusieurs fichiers
\n\nErreur n°1 : Oubli de déclarer un sous-module
\n\nVous avez créé le fichier network/tcp.rs et essayez de l'utiliser. Vous écrivez use network::tcp; — et obtenez une erreur de compilation. Pourquoi ? Parce que Rust ne scanne pas automatiquement les dossiers. Vous devez déclarer explicitement chaque sous-module.
// network/mod.rs\n// ❌ Erreur : le sous-module tcp n'est pas déclaré\n// use network::tcp; // ne compilera pas\n\n// ✅ Correct :\npub mod tcp; // déclarer le sous-module\n\n\nComment l'éviter : Vérifiez toujours que vous avez ajouté pub mod nom_du_sous-module; dans le module parent. C'est comme une importation explicite — Rust exige de la clarté.
Erreur n°2 : Confusion entre mod.rs et lib.rs
\n\nLes débutants placent souvent mod.rs à la racine du projet, à côté de main.rs. Cela fonctionne, mais seulement si vous créez une bibliothèque. Pour un fichier exécutable (main.rs), le module racine est main.rs lui-même. Et mod.rs est un fichier à l'intérieur d'un dossier.
my_project/\n├── main.rs // module racine pour le binaire\n├── lib.rs // module racine pour la bibliothèque (si elle existe)\n├── utils/\n│ ├── mod.rs // point d'entrée du module utils\n│ └── helpers.rs\n\n\nComment l'éviter : Retenez la règle : mod.rs ne vit qu'à l'intérieur d'un dossier-module. Si vous avez besoin d'un module racine pour une bibliothèque, utilisez lib.rs.
Erreur n°3 : Oubli de pub dans les sous-modules
\n\nVous avez déclaré un sous-module, mais vous ne pouvez toujours pas appeler une fonction. Vous avez probablement oublié de spécifier pub.
// network/mod.rs\npub mod tcp;\n\n// network/tcp.rs\n// ❌ La fonction est privée par défaut\nfn connect() { /* ... */ }\n\n// ✅ Rendre la fonction publique\npub fn connect() { /* ... */ }\n\n\nEn Rust, tout est privé par défaut. Ce n'est pas un bug, c'est une fonctionnalité : vous décidez ce que vous exposez au monde extérieur. Si une fonction est nécessaire en dehors du module, mettez pub.
Comment l'éviter : Utilisez pub de manière réfléchie. Pour les utilitaires internes, laissez l'accès privé. Pour l'API, rendez-le public.