Historiquement, Rust a été conçu dès le départ comme un langage pour écrire des programmes systèmes évolutifs et fiables. Le système de modules a été créé pour délimiter strictement les espaces de noms, isoler le code et organiser de grands projets sans conflits de noms. Les modules permettent de structurer le code, de cacher les détails d'implémentation et de gérer l'API publique.
Le problème est qu'avec la croissance d'un projet, il est nécessaire de se poser des questions sur l'isolation des composants, le partage de code et la gestion de la visibilité. Les erreurs sont souvent liées à une mauvaise utilisation des mots-clés pub, pub(crate), ainsi qu'à l'absence ou à une organisation incorrecte de la structure des répertoires et des fichiers.
Solution : en Rust, un module est déclaré avec le mot-clé mod ; les fichiers et répertoires structurent l'espace de noms, soulignant l'hiérarchie. Tout est privé par défaut, et les mots-clés pub, pub(crate), pub(super) permettent de gérer la visibilité. L'utilisation correcte des exports, des alias, ainsi qu'une bonne répartition du projet en modules rendent le code évolutif, maintenable et sécurisé.
Exemple de code :
// src/lib.rs mod network; pub use network::client::Client; // src/network/mod.rs pub mod client; // src/network/client.rs pub struct Client { pub name: String, }
Caractéristiques principales :
Que se passe-t-il si la structure du répertoire ne correspond pas aux définitions des modules ?
Le code ne se compilera pas : Rust s'attend à une correspondance stricte entre fichiers et modules (par exemple, si mod foo est déclaré, alors un fichier foo.rs ou un répertoire foo/mod.rs doit exister).
pub(crate) peut-il être utilisé pour masquer une implémentation des consommateurs externes, mais être accessible à tous les modules à l'intérieur du crate ?
Oui, pub(crate) rend l'élément visible dans n'importe quel module du même crate, mais invisible pour les projets externes qui utilisent ce crate comme dépendance.
Comment importer des fonctions d'un module profondément imbriqué dans le fichier racine sans réexportation publique (pub use) ?
Par une référence directe via la hiérarchie : crate::module::submodule::function. Sans pub use, elles ne seront accessibles qu'à l'intérieur du crate.
Dans le projet, le module réseau contient tous les composants du serveur, du client, du parseur de protocoles dans un seul fichier network.rs. Tout est déclaré pub, afin de tester, le code interne est directement connecté. Au fil du temps, la dépendance inutile augmente et il devient difficile de séparer l'interface publique de l'implémentation.
Avantages :
Inconvénients :
Le réseau est divisé en sous-modules : client, serveur, protocole. Seules les interfaces publiques sont exportées depuis le réseau, l'API est compacte, les détails sont encapsulés. Les tests pour chaque module sont isolés.
Avantages :
Inconvénients :