Historisch wurde Rust von Anfang an als Sprache für die Erstellung skalierbarer, zuverlässiger Systemprogramme konzipiert. Das Modulsystem wurde geschaffen, um Namensräume streng zu trennen, Code zu isolieren und große Projekte ohne Namenskonflikte zu organisieren. Module ermöglichen es, den Code zu strukturieren, Implementierungsdetails zu verbergen und eine öffentliche API zu verwalten.
Das Problem besteht darin, dass mit dem Wachstum des Projekts Fragen zur Isolierung von Komponenten, zur Wiederverwendbarkeit von Code und zum Management der Sichtbarkeit auftauchen. Fehler sind oft auf die falsche Verwendung der Schlüsselwörter pub, pub(crate) sowie auf fehlende oder fehlerhafte Organisation der Verzeichnis- und Dateistruktur zurückzuführen.
Lösung: In Rust wird ein Modul mit dem Schlüsselwort mod deklariert; Dateien und Verzeichnisse strukturieren den Namensraum und heben die Hierarchie hervor. Alles ist standardmäßig privat, während die Schlüsselwörter pub, pub(crate), pub(super) die Sichtbarkeit verwalten. Die korrekte Verwendung von Exporten, Aliassen sowie die durchdachte Aufteilung des Projekts in Module machen den Code skalierbar, wartbar und sicher.
Beispielcode:
// 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, }
Hauptmerkmale:
Was passiert, wenn die Verzeichnisstruktur nicht mit den Moduldifinierungen übereinstimmt?
Der Code wird nicht kompiliert: Rust erwartet eine strikte Übereinstimmung von Dateien und Modulen (wenn z.B. mod foo deklariert ist, muss die Datei foo.rs oder das Verzeichnis foo/mod.rs existieren).
Kann pub(crate) verwendet werden, um die Implementierung vor externen Verbrauchern zu verstecken, aber für alle Module innerhalb des Crates zugänglich zu sein?
Ja, pub(crate) macht das Element in jedem Modul des gleichen Crates sichtbar, jedoch unsichtbar für externe Projekte, die dieses Crate als Abhängigkeit verwenden.
Wie importiere ich Funktionen aus einem tief verschachtelten Modul in die Root-Datei ohne öffentliche Re-Exportierung (pub use)?
Durch direkten Bezug in der Hierarchie: crate::module::submodule::function. Ohne pub use sind sie nur innerhalb des Crates verfügbar.
Im Projekt enthält das Netzwerkmodul alle Komponenten des Servers, des Clients und des Protokollanalysators in einer Datei network.rs. Alles ist als pub deklariert, der interne Code wird direkt für Tests eingebunden. Im Laufe der Zeit wächst die unnötige Kopplung, und es wird schwierig, die öffentliche Schnittstelle von der Implementierung zu trennen.
Vorteile:
Nachteile:
Das Netzwerk wurde in Submodule unterteilt: client, server, protocol. Nur die öffentlichen Schnittstellen werden aus dem Netzwerk exportiert, das API ist kompakt, Details sind gekapselt. Tests für jedes Modul sind isoliert.
Vorteile:
Nachteile: