https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html[Link zum Buch]
== Packages, Crates, Modules, was?
Rust hat ein sehr hierachisches Konzept, was die Strukturierung von Projekten angeht.
Fangen wir mal von oben an:
=== Packages
Packages bestehen aus Crates.
Sie fassen diese also quasi zusammen und in `Cargo.toml` wird definiert, wie die Crates zu bauen sind.
Jedes Package, das wir bis jetzt erstellt haben, hatte standardmäßig eine "binary create" (dazu gleich mehr) im generierten Projekt.
Die Crates können (soweit wie ich das verstanden habe) in beliebigen Ordnern existieren, falls die Crate so heißen soll wie das Package, ist der Standardpfad `src/main.rs` (für binary) bzw. `src/lib.rs` (für library).
==== Warum mehrere Crates in einem Projekt?
Einfaches Beispiel: Man hat eine library crate, die Funktionen für einen Webserver bereitstellt.
Man kann dann einfach eine binary crate hinzufügen, die eine Referenz-Nutzung abbildet, also direkt ein Beispiel ist.
Dies hilft Nutzern direkt und gleichzeitig testet es direkt auch (wobei richtige Tests natürlich anders zu implementieren sind).
=== Crates
Creates sind die eigentlichen "Module".
Es gibt zwei Arten: binary und library.
==== Binary Crates
Diese Crates können zu einer ausführbaren Datei kompiliert werden.
Jedes der bisherigen Beispiele, z.B. auch das link:#/diary/rust/3[Higher-Lower-Spiel] sind eine solche binary crate.
Ihr Merkmal ist vor allem, dass eine `main`-Funktion existiert, die der Einstiegspunkt ist.
==== Library Crate
Wie der Name schon sagt, stellt diese Art Crate nur Funktionen zur verfügung wie eine Bibliothek.
=== Modules
Innerhalb einer Crate können Module existieren.
Und hier ist auch schon wieder von OOP abgeschaut.
Es können nämlich Rusts `private` und `public` hier genutzt werden.
Im Hauptprogramm kann mit `mod modulname;` das Modul eingebunden werden. Gesucht wird das Modul dann in `./modulname.rs` oder in `./modulname/mod.rs`, wobei letzteres aber aussieht, als wäre es die veraltete Version.
Zusätzlich kann auch direkt inline ein Modul erstellt werden.
let a = crate::testmodul::Teststruct::generator("Irgendein Wert");
// Geht
println!("Öffentlich: {}", a.oeffentlich);
// Geht nicht!
// println!("Privat: {}", a.privat);
}
----
Dagegen gilt für Enums: Wenn der Enum public ist, sind auch alle Varianten public.
==== Abürzungen mit `use`
Angenommen, wir haben eine Mediathek mit Filmen, Serien, Spielen, etc. und brauchen immer lange Zugriffspfade (also z.B. `crate::medien::spiele::liste::add()`), obwohl wir nur Spiele brauchen, kann `use` benutzt werden.
Wenn wir also `use crate::medien::spiele;` in unseren Code einfügen, können alle diese Befehle verkürzt werden auf eben z.B. `spiele::liste::add()`.
Theoretisch können wir das bis hin zu einzelnen Funktionsnamen machen, `se crate::medien::spiele::liste:add;`, würde `add()` im Scope verfügbar machen.
Dabei gibt es zwei Hinweise:
1. Es funktioniert nur, wenn sich zwei Namespaces nicht überschneiden. Ein Zufügen von `use andere::mod::add;` geht also nicht!
2. Das ganze gilt nur in genau diesem Scope. Falls wir jetzt ein weiteres Modul definieren, können wir darin nicht die Pfade kürzen.
Und für beides gibt es Umwege:
1. Man kann `use andere::mod::add as modAdd;` benutzen.
2. Sollten wir `pub use ...` benutzen, kann tatsächlich diese Abkürzung benutzt werden.
`pub use` kann auch benutzt werden, alle möglichen Module in seiner Crate miteinander reden zu lassen, aber nach außen nur bestimmte Schnittstellen freizugeben.