Code-Review in Rust: Was prüfen und wie Feedback geben

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung

Code Review ist ein wesentlicher Bestandteil der professionellen Softwareentwicklung. Im Rust-Ökosystem, wo Speichersicherheit und Leistung an erster Stelle stehen, bekommt das Code-Review eine besondere Bedeutung. Die falsche Verwendung von unsafe, das Ignorieren der Ownership-Regeln oder implizite Panics können alle Vorteile der Sprache zunichtemachen.

In diesem Artikel besprechen wir, worauf man beim Code-Review in Rust achten sollte, wie man Feedback strukturiert und welche Tools bei der Automatisierung von Prüfungen helfen. Das Material ist sowohl für Anfänger als auch für erfahrene Entwickler nützlich, die den Review-Prozess optimieren möchten.



1. Sicherheit: Prüfung von unsafe-Code und impliziten Panics

Rust garantiert Speichersicherheit, aber unsafe bedeutet den Verzicht auf diese Garantien. Jeder unsafe-Block muss sorgfältig geprüft werden.



Was ist in unsafe-Code zu prüfen?

  • Korrektheit von Zeigern: Gibt es Dereferenzierungen von Null- oder Hängenden Zeigern?
  • Datenausrichtung: Ist die Ausrichtung bei der Konvertierung von Rohzeigern korrekt?
  • Aliasing: Gibt es Verstöße gegen Aliasing-Regeln (z. B. gleichzeitige mutable und immutable Ausleihen)?
  • Invarianten: Werden die Invarianten von Datenstrukturen eingehalten (z. B. bleibt ein binärer Heap ein Heap)?


// Schlechtes Beispiel: unsichere Konvertierung ohne Prüfung der Ausrichtungfn bad_unsafe(data: &[u8]) -> &[u32] {    unsafe {        std::slice::from_raw_parts(            data.as_ptr() as *const u32,            data.len() / 4        )    }}

// Gutes Beispiel: mit Prüfung der Ausrichtungfn good_unsafe(data: &[u8]) -> Option<&[u32]> { if data.len() % 4 != 0 || data.as_ptr() as usize % 4 != 0 { return None; } Some(unsafe { std::slice::from_raw_parts( data.as_ptr() as *const u32, data.len() / 4 ) })}


Implizite Panics

In Rust gibt es viele Operationen, die eine Panic auslösen können: unwrap(), expect(), panic!(), Division durch Null, Zugriff außerhalb der Array-Grenzen. Beim Code-Review sollte man darauf achten:

  • Verwenden Sie unwrap() nur in Tests oder wenn ein Fehler wirklich unmöglich ist.
  • Bevorzugen Sie unwrap_or(), unwrap_or_else() oder die Verarbeitung mit match.
  • Prüfen Sie, ob alle as-Konvertierungen keine Daten verlieren (z. B. u64 as u32).


// Schlecht: implizite Paniclet value = some_option.unwrap();

// Gut: explizite Verarbeitunglet value = some_option.unwrap_or_else(|| { log::error!("Missing expected value"); default_value()});


2. Ownership und Borrowing: Typische Fehler

Das Ownership-System ist die Hauptbesonderheit von Rust. Compiler-Fehler sind hier die besten Freunde, aber Code-Review hilft, logische Fehler zu finden, die der Compiler nicht abfängt.



Übermäßiges Klonen

Ein häufiges Problem ist das Klonen, wo eine Referenz übergeben werden könnte. Dies reduziert die Leistung und erhöht die Speichernutzung.



// Schlecht: Klonen des gesamten Stringsfn process(data: Vec<String>) {    for item in data {        let cloned = item.clone();        do_something(&cloned);    }}

// Gut: Übergabe einer Referenzfn process(data: &[String]) { for item in data { do_something(item); }}


Unnötige Ausleihen und Lifetimes

Prüfen Sie, ob die Lebensdauer von Referenzen nicht zu lang ist. Manchmal kann man die Funktionssignatur vereinfachen, indem man überflüssige Lifetime-Annotationen entfernt.



// Komplex: überflüssige Lifetimesfn longest<'a>(x: &'a str, y: &'a str) -> &'a str {    if x.len() > y.len() { x } else { y }}

// Wenn

Blogs

Buchempfehlungen