Sollte ich es vermeiden, in der Produktionsanwendung auszupacken?

8

Es ist einfach, zur Laufzeit mit unwrap :

abzustürzen %Vor%

Ergebnis:

%Vor%

Ist unwrap nur für schnelle Tests und Proofs konzipiert?

Ich kann nicht bestätigen "Mein Programm wird hier nicht abstürzen, daher kann ich unwrap " verwenden, wenn ich panic! zur Laufzeit wirklich vermeiden möchte, und ich denke, in einer Produktionsanwendung wollen wir panic! vermeiden .

Mit anderen Worten, kann ich sagen, dass mein Programm zuverlässig ist, wenn ich unwrap verwende? Oder muss ich unwrap vermeiden, auch wenn der Fall einfach erscheint?

Ich lese diese Antwort:

  

Es wird am besten verwendet, wenn Sie sicher sind, dass Sie keinen Fehler haben.

Aber ich glaube nicht, dass ich "positiv sicher" sein kann.

Ich glaube nicht, dass dies eine Frage der Meinung ist, sondern eine Frage über den Kern von Rust und die Programmierung.

    
rap-2-h 13.09.2016, 19:33
quelle

4 Antworten

17

Während das ganze "Error Handling" -Thema sehr kompliziert und oft meinungsbezogen ist, kann diese Frage hier eigentlich beantwortet werden, denn Rust hat eine eher enge Philosophie. Das ist:

  • panic! für Programmierfehler ("bugs")
  • korrekte Fehlerausbreitung und -behandlung mit Result<T, E> und Option<T> für erwartete und behebbare Fehler

Man kann sich unwrap() als umwandeln zwischen diesen beiden Arten von Fehlern vorstellen (es konvertiert einen behebbaren Fehler in ein panic!() ). Wenn Sie unwrap() in Ihr Programm schreiben, sagen Sie:

  

An diesem Punkt ist ein None / Err(_) -Wert ein Programmierfehler und das Programm kann es nicht wiederherstellen.

Beispiel: Sie arbeiten mit HashMap und möchten einen Wert einfügen, den Sie später ändern möchten:

%Vor%

Hier verwenden wir unwrap() , weil wir sicher sein können, dass der Schlüssel einen Wert enthält. Es wäre ein Programmierfehler, wenn es nicht und noch wichtiger wäre: Es ist nicht wirklich wiederherstellbar. Was würdest du tun, wenn es zu diesem Zeitpunkt keinen Wert mit dem Schlüssel "peter" gibt? Versuchen Sie es erneut einzufügen ...?

Aber wie Sie vielleicht wissen, gibt es eine schöne entry API für die Karten in der Standardbibliothek von Rust. Mit dieser API können Sie all diese unwrap() s vermeiden. Und das gilt für fast alle Situationen: Sie können Ihren Code sehr oft umstrukturieren, um unwrap() zu vermeiden! Nur in sehr wenigen Situationen gibt es keinen Weg dorthin. Aber dann ist es in Ordnung, es zu verwenden, wenn Sie signalisieren wollen: An diesem Punkt wäre es ein Programmierfehler.

Es gab kürzlich einen ziemlich populären Blogbeitrag zum Thema "Fehlerbehandlung", dessen Schlussfolgerung der Philosophie von Rust ähnelt. Es ist ziemlich lang, aber es lohnt sich, es zu lesen: "Das Fehlermodell" . Hier ist mein Versuch, den Artikel in Bezug auf diese Frage zusammenzufassen:

  • unterscheidet bewusst zwischen Programmierfehlern und wiederherstellbaren Fehlern
  • Verwenden Sie einen "fail fast" -Ansatz für die Programmierung von Fehlern

Zusammenfassend : Verwenden Sie unwrap() , wenn Sie sicher sind, dass der wiederherstellbare Fehler, den Sie erhalten, tatsächlich zu diesem Zeitpunkt nicht behebbar ist. Bonuspunkte zum Erklären von "warum?" in einem Kommentar über der betroffenen Zeile ;-)

    
Lukas Kalbertodt 13.09.2016, 20:06
quelle
4
  

Mit anderen Worten, kann ich sagen, dass mein Programm zuverlässig ist, wenn ich unwrap verwende? Oder muss ich das Auspacken vermeiden, selbst wenn der Fall einfach erscheint?

Ich denke, mit unwrap vernünftig umzugehen ist etwas, das man lernen muss zu handhaben, es kann nicht einfach vermieden werden.

Meine rhetorische Frage Sperrung wäre:

  1. Kann ich sagen, dass mein Programm zuverlässig ist, wenn ich Indizierung für Vektoren, Arrays oder Slices verwende?
  2. Kann ich sagen, dass mein Programm zuverlässig ist, wenn ich eine Ganzzahl-Division verwende?
  3. Kann ich sagen, dass mein Programm zuverlässig ist, wenn ich Nummern hinzufüge?

(1) ist wie unwrap, Indizierung Panics, wenn Sie eine Vertragsverletzung machen und versuchen, außerhalb der Grenzen zu indizieren. Dies wäre ein Programmfehler, der jedoch weniger Aufmerksamkeit auf sich zieht als ein Aufruf von unwrap .

(2) ist wie unwrap, wenn der Divisor Null ist, wird eine Integer-Division ausgelöst.

(3) unterscheidet sich im Gegensatz zu "unwrap" nicht von einem Überlauf in Releasebuilds. Daher kann es im Hintergrund zu Wraparound- und logischen Fehlern führen.

Natürlich gibt es Strategien, um all diese zu behandeln, ohne panische Fälle im Code zu lassen, aber viele Programme verwenden einfach zum Beispiel die Überprüfung der Grenzen, wie es ist.

    
bluss 13.09.2016 21:47
quelle
2

Hier sind zwei Fragen zusammengefaßt:

  • ist die Verwendung von panic! in der Produktion akzeptabel
  • ist die Verwendung von unwrap in der Produktion akzeptabel

panic! ist ein Werkzeug, das in Rust verwendet wird, um unwiederbringliche Situationen / verletzte Annahmen zu signalisieren. Es kann verwendet werden, um entweder ein Programm zum Absturz zu bringen, das möglicherweise angesichts dieses Fehlers nicht fortfahren kann (zum Beispiel OOM-Situation), oder um den Compiler zu umgehen, der weiß, dass es (momentan) nicht ausgeführt werden kann.

unwrap ist eine Bequemlichkeit, die in der Produktion am besten vermieden wird. Das Problem mit unwrap ist, dass es nicht angibt, welche Annahme verletzt wurde, stattdessen ist es besser, expect("") zu verwenden, was funktional äquivalent ist, aber auch einen Hinweis darauf gibt, was schief gelaufen ist (ohne den Quellcode zu öffnen) / p>     

Matthieu M. 14.09.2016 06:47
quelle
1

unwrap() ist nicht unbedingt gefährlich. Genau wie bei unreachable!() gibt es Fälle, in denen Sie sicher sein können, dass keine Bedingung ausgelöst wird.

Funktionen, die Option oder Result zurückgeben, sind manchmal nur für eine größere Bandbreite von Bedingungen geeignet, aber aufgrund der Struktur Ihres Programms treten diese Fälle möglicherweise nie auf.

Beispiel: Wenn Sie einen Iterator aus einem Vec tor erstellen, wissen Sie seine genaue Länge und können sicher sein, wie lange next() aufgerufen wird, um einen Some<T> zurückzugeben (und Sie können sicher unwrap() es).

    
ljedrz 13.09.2016 19:53
quelle

Tags und Links