Eiffel は、例外の代わりにオブジェクトの状態を使用することを提唱しています。その場合、クライアントは、エラーが発生した場合に何を期待するかを理解し、適切に処理できます。例えば、
has_error: BOOLEAN
-- Has operation terminated with an error?
error_code: INTEGER
-- Last error code or `no_error'.
is_closed: BOOLEAN
-- Is connection closed?
response: detachable RESPONCE
-- Last response if `not has_error'.
send_request (data: REQUEST)
require
is_open: not is_closed
do
...
ensure
is_closed: is_closed implies (has_error and not connection.is_open)
is_successful: not has_error implies attached response
end
その後、クライアントはサプライヤ オブジェクトの状態について推論し、予測可能な方法でそれを使用し続けることができます。
interface.send_request (...)
if interface.is_closed then
... -- The connection is unusable and should be reestablished.
elseif interface.has_error then
... -- Inspect `interface.error_code', possibly trying to resend the request.
else
... -- Use `interface.response' to continue processing.
end
例外が存在する場合、一部のドキュメントを除いて、どのような場合に何をすべきかを推測することはできません。response
また、上記のコードで の使用が完全に有効であることを簡単に確認できる自動ツールを使用できなくなります。
rescue
スタックの奥深くでエラーが発生した場合は、 /で例外メカニズムを使用できますretry
。ただし、ネットワーク障害の詳細とは関係のない、低レベルのネットワーク コンポーネントとユーザー インターフェイスとの間の密接な結合が生じる可能性があります。最も単純なケースでは、ネットワーク クラスは{EXCEPTIONS}.raise
適切なメッセージで呼び出します。より具体的なアプローチは、型EXCEPTION
(または子孫) のオブジェクトを作成し、それを呼び出して対応するメッセージを設定し、呼び出しset_description
て例外を発生させることraise
です。例外を処理するユーザー コードは次のようになります。
local
is_retried: BOOLEAN
e: EXCEPTIONS
do
if is_retried then
-- There was an exception, handle it.
create e
if e.developer_exception_name ~ "This error" then
... -- Do something.
elseif e.developer_exception_name ~ "That error" then
... -- Do something else.
else
... -- Report yet another error.
end
else
... -- Some code that may fail with an exception.
end
rescue
if not is_retried then
is_retried := True
retry
end
end
編集
ネストされたエラーを処理する特定の方法は、アプリケーションの設計に依存し、言語とは無関係のようです。可能な代替手段は次のとおりです。
(例外メカニズムが使用されている場合は、お勧めしません。 ) (下位レベルの) 例外をキャッチし、それを処理してクラスの不変条件を復元した後、前の例外をキャンセルせずに新しい例外が発生します。その後、クエリ{EXCEPTION}.cause
を (再帰的に) 使用して、ネストされた例外オブジェクトにアクセスできます。
前のものと同様のメカニズムを使用できます。ただし、新しいオブジェクトを作成する代わりに、クラスは詳細の要求を下位レベルのクラスに委任できます。例えば、
class A feature
has_error: BOOLEAN
do
Result := nested.has_error
end
error: STRING
do
Result := "Cannot complete operation X. Reason: " + nested.error
end
feature {NONE}
nested: B
end
class B feature
has_error: BOOLEAN
do
Result := nested.has_error
end
error: STRING
do
Result := "Cannot complete operation Y. Reason: " + nested.error
end
feature {NONE}
nested: C
end
ロギング機能を使用できます。エラーの重大度を区別したり、ソースを指定したりできます。
class A feature
do_something
do
nested.whatever
if nested.has_error then
log.error ("Cannot complete operation X.")
end
end
has_error: BOOLEAN do Result := nested.has_error end
feature {NONE}
nested: B
end
class B feature
whatever
do
nested.try_something
if nested.has_error then
-- An error has been reported by "nested".
elseif something_else_goes_wrong then
has_inner_error := True
log.error ("Something goes wrong.")
elseif has_minor_issues then
log.warning ("Be careful.")
end
end
has_error: BOOLEAN do Result := nested.has_error or has_inner_error end
has_inner_error: BOOLEAN
-- Some error that is not one of the errors reported by `nested'.
feature {NONE}
nested: C
end