Ich werde Wert definieren. Aber dieser Wert kann im Wert des Schlüssels des Hashes sein. Ich verwende rescue für define Wert ist Null, wenn dieser Schlüssel nicht existiert. zum Beispiel
foo = bar[:a][:b][:c] rescue nil
Aber sag mir in der Praxis einen schlechten Stil, weil ich Rettung in seiner Modifikatorform benutze. Ich werde die Logik ändern, um die Check-Drei-Bedingung zu verwenden.
foo = bar[:a][:b][:c] if bar.key?(:a) && bar[:a].key?(:b) && bar[:a][:b].key?(:c)
Ich würde wirklich gerne wissen Warum sollten wir vermeiden, Rettung in seiner Modifikationsform in Schienen zu verwenden?
Warum sollten wir vermeiden, Rettung in seiner Modifikationsform in Schienen zu verwenden?
Erstens, weil es alle Fehler verbirgt, einschließlich der erwarteten und der, die Sie nicht haben, und eine Decke rescue
macht es zukünftigen Lesern Ihres Codes nicht klar < em> welche Fehler wurden erwartet oder unerwartet. Dies ist vielleicht kein Problem now , mit einem einfachen foo[:a][:b][:c]
, aber zu irgendeinem Zeitpunkt könnte jemand diese Anweisung ändern, um foo[:a][:b][some_method]
zu lesen und plötzlich alle Fehler, die sollten bubble aus some_method
werden ebenfalls verschluckt.
Zweitens gibt es normalerweise eine bessere, weniger allumfassende Lösung, die expliziter entworfen wurde, um nur den Fehler zu behandeln, den Sie ignorieren wollen: Ein fehlender Index oder ein nil
Rückgabewert.
In Ihrem Fall ist die Alternative nicht die massive if && && &&
, die Sie vorschlagen. Für einen Hash können Sie entweder dig
verwenden alle Vorteile von rescue
, ohne jede Art von Ausnahme zu verschlingen, die ausgelöst werden könnte:
Ebenso können Sie für verkettete Methodenaufrufe try
(in Rails) oder den sicheren Navigationsoperator (in Ruby 2.3) verwenden:
Die längere Form ist sicherer, ich würde die Kurzversion in der Produktion nicht verwenden, außer es gibt keinen anderen Weg. Ob Sie Prüfungen oder Ausnahmen verwenden, um Fehler zu vermeiden oder zu erfassen, hängt von der Situation ab. Ausnahmen sind teuer in der Prozessorzeit, so sind Ihre Benchmarks für zeitaufwendige Methoden, auf der anderen Seite eine Menge Prüfungen und noch nicht sicher ist, ist vielleicht noch schlimmer. Wenn die Lesbarkeit meines Codes durch eine Menge von Prüfungen verloren gehen würde und die Geschwindigkeit kein Faktor ist, benutze ich begin .. rescue oder def .. rettung, aber in diesem Fall ist es besser, eine bekannte Ausnahme wie diese zu retten.
> %Vor%Was gibt
%Vor%Fange immer die Art der Ausnahme und setze oder besser logge sie, ich benutze sie auch, um eine Variable @errors zu erzeugen, die für alle meine Skripte protokolliert und von einem separaten Tool überwacht wird.
Vermeiden
%Vor%aus dem gleichen Grund wie
%Vor%Weder gibt eine Ausnahmeklasse an und überspringt somit stillschweigend ALLE Fehler und nicht nur die erwartete. Sie sollten immer so genau wie möglich sein, wenn Sie Fehler beheben.
Außerdem entstehen beim Erstellen einer Ausnahme große Kosten.
Wenn Sie eine Exception auslösen, ist das Backtrace ausgefüllt, und in Rails bedeutet das Erstellen von 500 bis 1000 Strings mit Dateinamen und Zeilennummern, da Rails tendenziell einen tiefen Callstack hat. Wenn Sie also Ihre rescue nil
in eine Schleife einfügen, kann es leicht passieren, dass Sie Tausende von String-Objekten erstellen, die niemals verwendet werden, und mit Rubys abgründiger Speicherbereinigung wirkt sich dies auf Ihre Leistung aus.
Versuchen Sie daher nach Möglichkeit, Alternativen zu verwenden, die keine Ausnahme auslösen
%Vor%Ein typisches Beispiel, warum es eine schlechte Idee ist:
%Vor% Sie könnten viel Zeit verlieren, indem Sie überprüfen, dass bar
wirklich {a: {b: {c: :something}}}
hat und sich fragt, warum foo
ist nil
: Es gibt einen Tippfehler und rescue nil
verbirgt es.
Alternativen finden Sie in @ meagars guter Antwort.
Tags und Links ruby error-handling