質問
プログラミングRubyの本を読んでいて、次の概念を理解するのに問題があります:
- 著者は「一時的な例外」について話します。コード内で発生する可能性があり、それらを処理する独自の例外オブジェクトの作成を提案します。一時的なエラーとは何か、独自のExceptionオブジェクトを作成するのが適切なタイミングを完全に理解しているとは思いません。彼は例外の定義について話すとき、第6章でそれについて話します:
たとえば、特定の種類のネットワークエラーは一時的なものである可能性があります。第6章97ページ。例外への情報の追加。
- また、ルビーでのキャッチアンドスローの使用を回避するのに苦労しています。これはレイズアンドレスキューよりも優れているのはいつですか?
解決
「一時的な例外」への参照ページを教えてください。ライン?
いずれの場合でも、いつでも新しい例外を作成できます。通常は、障害に関する詳細情報を転送できるように作成することをお勧めします。これは、低レベルの例外があり、ユーザーにとってより意味のあるものにしたい場合に特に便利です。
RubyのThrow / Catchは、実際にはCのsetjmp / longjmpのような一種の非ローカルgotoですが、動作が改善されています。実行を長い間転送したいときにいつでも使用できます。
明らかに、 goto
をあまり使いたくないのと同じ理由で、これをしたくありません。使用する大きな理由は、実行を継続する必要があるプログラムの場合であるため、特定の種類のエラーをキャッチした場合、実行中の作業全体をダンプして最初に戻ることができます。
さて、それは私が持っているつるはしの本のどちらの版の97ページにも載っていないようですが、私はそれが何を意味するか見ます。 ...ああ、ここにあります、第3版の157ページ。
まず、「一時的」についてのビジネスでは、発生する可能性のあるネットワークの問題がいくつかあります。たとえば、BOFHがネットワークケーブルを抜き、再び差し込むと、問題が発生します。パニックする前に落ち着いて再試行するために数秒を与えたいかもしれません。どうしますか?
この場合、新しい種類の例外を定義してもらいます。これは継承のみで行われます:
class RetryException < RuntimeError
# so this is a kind of RuntimeError which is a kind of Exception
attr: ok_to_retry
def initialize(ok_to_retry)
@ok_to_retry
end
end
したがって、何か問題が発生した場合、これらの新しい再試行可能な例外を発生させることができます
raise RetryException.new(true), "transient read error"
これは、スタックの一種のRuntimeErrorである何かを送信しますが、追加情報、つまり「はい、これは再試行できます」というフラグが付加されています。
さて、ここにRubyの本当に気の利いたものがあります:いくつかのことを再試行する機能が組み込まれています。スタックのどこかに、次のコードがあります:
begin
# do something that raises this exception
do_something()
rescue RetryException => detail
# if the exception is one of these retryable ones,
# catch it here, but it in detail
if detail.ok_to_retry
retry
end
# this means exactly the same as 'retry if detail.ok_to_retry`
# from the book, btw
# if it STILL doesn't work, send the exception on
raise # just re-raises the last exception
end