Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Note

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Kapitel 01b: Der 8-Wochen-Trainingsplan (Sicht für Profis)

Für Entwickler mit fundierten Vorkenntnissen (C++, Java, Go, Python) ist dieser Plan darauf ausgelegt, die mentalen Konzepte umzutrainieren. Sie müssen nicht lernen, wie man programmiert, sondern wie man ohne Garbage Collector und ohne manuelle Speicherfehler hochperformante Systeme entwirft.


Woche 1: Statische Typsicherheit & Cargo-Workflow (Kapitel 01 - 03)

  • Fokus: Typsystem, Typinferenz, Shadowing, Konstanten vs. Variablen.
  • Architektur-Fokus: Verstehen Sie, warum Rust keine impliziten Typkonvertierungen erlaubt (z.B. kein automatischer Cast von i32 zu f64). Nutzen Sie Shadowing zur Transformation von Datentypen innerhalb desselben Scopes, um Namenskonflikte zu vermeiden und Unveränderlichkeit zu wahren.
  • Kernfrage: Warum ist Shadowing speicher- und laufzeiteffizienter als veränderlicher Zustand (mut)?
  • Compilerfehler:
    #![allow(unused)]
    fn main() {
    let x: i32 = 10;
    let y: f64 = x; // Compilerfehler: Typen stimmen nicht überein
    }
    Lösung: Expliziter Cast mit let y = x as f64;. Rust erzwingt absolute Klarheit auf Typebene, um verdeckte Rechenungenauigkeiten zu verhindern.

Woche 2: Die RAII-Revolution: Ownership & Lifetimes (Kapitel 04 & 05)

  • Fokus: Resource Acquisition Is Initialization (RAII), Compile-Time Memory Management, Borrow Checker.
  • Architektur-Fokus: Rust verschiebt das Ressourcenmanagement komplett in den Compiler. Ein Wert hat genau einen Eigentümer. Wird dieser ungültig, wird die Ressource freigegeben. Referenzen werden statisch über Lebensdauern (Lifetimes) analysiert.
  • Kernfrage: Wie verhindert der Borrow Checker zur Kompilierzeit Use-after-free und Double-free?
  • Compilerfehler:
    #![allow(unused)]
    fn main() {
    let r;
    {
        let x = 5;
        r = &x; // Compilerfehler: `x` lebt nicht lange genug
    }
    println!("{}", r);
    }
    Lösung: Die Lebenszeit von x muss mindestens so lang sein wie die von r. Rust verhindert Dangling Pointers statisch.

Woche 3: Datenkapselung ohne Klassenhierarchien (Kapitel 06 & 10)

  • Fokus: Structs, Composition over Inheritance, Datenstrukturen der Standardbibliothek.
  • Architektur-Fokus: Trennen Sie Daten (Structs) strikt von Verhalten (impl-Blöcke). Vermeiden Sie zyklische Objektreferenzen. Entwerfen Sie Datenstrukturen als gerichtete Graphen.
  • Kernfrage: Warum verbietet Rust die Vererbung auf Datenebene und wie wird Polymorphie stattdessen realisiert?
  • Compilerfehler: Versuch, zwei Structs über gegenseitige veränderbare Referenzen zu verknüpfen. Dies führt zu permanenten Konflikten mit dem Borrow Checker. Lösung: Datenflüsse linearisieren oder Indizes in einem Vector nutzen statt roher Pointer.

Woche 4: Fehler als Daten & Funktionale Closures (Kapitel 07 & 09)

  • Fokus: Monadische Fehlerbehandlung, Closures als Typen.
  • Architektur-Fokus: Keine Exceptions. Fehler sind normale Rückgabetypen (Result<T, E>). Der ?-Operator erlaubt eine elegante Fehlerweiterleitung. Closures implementieren automatisch einen der drei Traits: Fn, FnMut oder FnOnce, abhängig davon, wie sie Variablen aus ihrer Umgebung einfangen.
  • Kernfrage: Was unterscheidet die Speicherallokation von Fn (unveränderlicher Borrow) von FnOnce (Konsumierung des Scopes)?
  • Compilerfehler: Nutzung einer Variable nach ihrer Konsumierung durch eine FnOnce-Closure. Lösung: Variable vor der Closure klonen oder die Closure so definieren, dass sie nur Referenzen einfängt.

Woche 5: Algebraische Datentypen (Kapitel 08 & 12)

  • Fokus: Pattern Matching, Enums mit Datenpayload.
  • Architektur-Fokus: Nutzen Sie Enums zur Darstellung komplexer Zustandsmaschinen. Jede Enum-Variante kann unterschiedliche Datenstrukturen aufnehmen. Der Compiler garantiert, dass alle Zustände in match-Blöcken behandelt werden.
  • Kernfrage: Wie optimiert der Compiler Enums mit Option<&T> über die Null-Pointer-Optimierung?
  • Compilerfehler: Fehlende Abdeckung einer Enum-Variante im match-Block. Lösung: Fügen Sie die Variante hinzu oder nutzen Sie den Catch-All-Zweig (_).

Woche 6: API-Design, Generics & Module (Kapitel 11, 13 & 14)

  • Fokus: Traits, Generische Typen, Monomorphisierung.
  • Architektur-Fokus: Definieren Sie wiederverwendbare APIs über Traits. Verwenden Sie statischen Dispatch (impl Trait), um zur Kompilierzeit spezialisierten Code zu erzeugen (Zero-Cost). Nutzen Sie dynamischen Dispatch (dyn Trait) nur bei heterogenen Collections zur Laufzeit.
  • Kernfrage: Wie wirkt sich Monomorphisierung auf die Codegröße (Code Bloat) und die Ausführungsgeschwindigkeit aus?
  • Compilerfehler: Versuch, einen Trait mit assoziierten Typen in einem Vektor vom Typ Vec<Box<dyn MeinTrait>> zu speichern. Lösung: Nutzen Sie stattdessen Generics oder löschen Sie die assoziierten Typen aus dem Trait (Objektsicherheit).

Woche 7: Concurrency & Asynchronität (Kapitel 15 & 16)

  • Fokus: Data-Race-Freiheit, Send/Sync-Traits, Futures, Async/Await.
  • Architektur-Fokus: Rust garantiert die Abwesenheit von Data Races zur Kompilierzeit. Typen, die sicher an andere Threads übergeben werden können, implementieren Send. Typen, deren Referenzen sicher geteilt werden können, implementieren Sync.
  • Kernfrage: Wie arbeiten Arc und Mutex zusammen, um threadsicheren, veränderlichen Zustand zu ermöglichen?
  • Compilerfehler: rc::Rc<T> cannot be sent between threads safely (Fehlender Send-Trait bei Rc). Lösung: Ersetzen Sie Rc im Multi-Thread-Kontext durch Arc.

Woche 8: Systemnahe Programmierung & Metaprogrammierung (Kapitel 17 - 20)

  • Fokus: Makros, Unsafe Rust, FFI, Testabdeckung.
  • Architektur-Fokus: Verwenden Sie unsafe, um mit C-Bibliotheken zu interagieren oder hochperformante, hardwarenahe Datenstrukturen zu schreiben. Kapseln Sie unsicheren Code immer hinter einer sicheren, idiomatischen API.
  • Kernfrage: Warum führt unsicherer Code in einem unsafe-Block nicht automatisch dazu, dass Rusts Typsicherheitsgarantien im restlichen Programm verfallen?
  • Compilerfehler: Versuch, rohe Zeiger außerhalb eines unsafe-Blocks zu dereferenzieren. Lösung: Packen Sie den Zugriff in ein unsafe { ... } Konstrukt.

Note

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).