Einleitung: Warum Code-Review in Rust nicht nur eine Formalität ist
\n\nCode-Review ist einer der Schlüsselprozesse in der Entwicklung jeder qualitativ hochwertigen Software. Aber wenn es um Rust geht, bekommt dieser Prozess eine besondere Bedeutung. Rust ist eine Sprache mit einem einzigartigen System von Ownership und Borrowing, das der Compiler bereits zur Kompilierzeit prüft. Doch selbst wenn der Code kompiliert, bedeutet das nicht, dass er gut, sicher und effizient geschrieben ist.
\n\nIn diesem Artikel besprechen wir, worauf genau bei Code-Reviews von Rust-Projekten zu achten ist, wie man konstruktives Feedback gibt, um Kollegen nicht zu verletzen, und wie man typische Fehler vermeidet, die der Compiler nicht abfängt. Der Artikel richtet sich an Entwickler, die bereits mit den Grundlagen von Rust vertraut sind, aber ihre Review-Fähigkeiten vertiefen möchten.
\n\n1. Speichersicherheit und Ressourcenverwaltung
\n\nRust garantiert Speichersicherheit ohne Garbage Collector. Das entbindet jedoch nicht von der Notwendigkeit zu prüfen, wie der Entwickler unsafe-Blöcke, rohe Zeiger und externe FFI-Aufrufe verwendet.
Was prüfen:
\n- \n
- Verwendung von
unsafe: Jederunsafe-Block muss gerechtfertigt und mit einem Kommentar versehen sein, warum er sicher ist. Wenn es ohneunsafegeht, ist das besser. \n - Ressourcenlecks: Prüfen Sie, ob alle
Box,Rc,Arcund andere intelligente Zeiger korrekt freigegeben werden. Zyklische Referenzen überRcohneWeaksind beispielsweise ein häufiges Problem. \n - Drop-Reihenfolge: Wenn eine Struktur Felder mit einer benutzerdefinierten
Drop-Implementierung enthält, stellen Sie sicher, dass die Zerstörungsreihenfolge nicht zu Fehlern führt. \n
// Beispiel für schlechten Code: unsafe ohne Kommentare\nunsafe {\n let ptr = ...;\n // Keine Erklärung, warum dies sicher ist\n *ptr = 42;\n}\n\n// Guter Code: Kommentar und sichere Alternative\n// Verwende unsafe nur für den Aufruf einer C-Funktion, die die Gültigkeit des Zeigers garantiert\nunsafe {\n // Der Zeiger wurde von der C-API erhalten, die seine Gültigkeit während der Lebensdauer des Aufrufs garantiert\n some_c_function(ptr);\n}\n\n\n2. Idiomatischer Code und Stil
\n\nRust hat seine eigenen Redewendungen, die sich von C++ oder Python unterscheiden. Code-Reviews sollten prüfen, wie sehr der Code dem Geist der Sprache entspricht.
\n\nWas prüfen:
\n- \n
- Verwendung von
OptionundResult: Vermeiden Sieunwrap()undexpect()ohne triftigen Grund. Verwenden Sie in Produktionscode die Fehlerbehandlung mitmatch, dem?-Operator oderunwrap_or_else. \n - Pattern Matching: Bevorzugen Sie
if letundmatchanstelle von Ketten vonis_some()/is_ok(). \n - Verwendung von Traits: Prüfen Sie, ob Traits sinnvoll implementiert sind. Beispielsweise sollte die Implementierung von
Displayeine lesbare Ausgabe liefern, nicht nurDebug. \n - Benennung: In Rust ist es üblich,
snake_casefür Variablen und Funktionen zu verwenden,CamelCasefür Typen und Traits. Konstanten verwendenSCREAMING_SNAKE_CASE. \n
// Schlecht: übermäßige Verwendung von unwrap\nlet value = some_option.unwrap();\n\n// Gut: Fehlerbehandlung\nlet value = match some_option {\n Some(v) => v,\n None => return Err("Value not found".into()),\n};\n\n// Noch besser: mit dem ?-Operator\nlet value = some_option.ok_or("Value not found")?;\n\n\n3. Leistung und Allokationen
\n\nRust bietet eine low-level Kontrolle über den Speicher, aber das bedeutet nicht, dass der Code automatisch schnell ist. Beim Review ist es wichtig, potenzielle Engpässe zu prüfen.
\n\nWas prüfen:
\n- \n
- Überflüssige Allokationen: Prüfen Sie, ob unnötig
StringoderVec