Option / Maybeが良いアイデアと考えられ、チェックされた例外はそうではないのはなぜですか?


23

Scalaなどの一部のプログラミング言語には、値を含む場合と含まない場合があるOption型(とも呼ばれるMaybe)の概念があります。

それらについて私が読んだことから、彼らは広くこの問題に対処するより優れた方法であると考えられていますnull。なぜなら、ランタイム中に単に爆発するのではなく、値がない場合を考慮するようにプログラマーに明示的に強制するためです。

一方、Javaでチェックされた例外は悪い考えと見なされるようで、Javaはそれらを実装する唯一の広く使用されている言語のようです。しかし、その背後にある考え方Optionは、例外がスローされる可能性があるという事実にプログラマーに明示的に対処させるために、型にいくらか似ているようです。

Option型にないチェック済み例外には、いくつかの追加の問題がありますか?または、これらのアイデアは私が思うほど似ていないのか、例外ではなくオプションの明示的な処理を強制する正当な理由がありますか?


Either e aデータ型も参照してください。

4
確認済み例外について:進化するコードベースと欠落/古いドキュメントを備えた多数のオープンソースおよび内部Javaライブラリのユーザーとして、Javaは明示的に宣言される特定の例外を強制しないと考えて震えています。これは、予期せず、悪い場所で発生する未処理のランタイムエラーの悪夢です。そして、Java7は最終的に例外処理をほぼ正常にし、古いtry-catchの乱雑さの多くを取り除きます。
ハイド

回答:


24

Optionsは構成可能であるため。上の便利なメソッドがたくさんありOption、まだ流れの正確な制御を可能にしながら、あなたが簡潔なコードを書くことができ、: 、mapflatMaptoListflattenより。これはOption、特定の種類のモナドであり、作成方法が非常によくわかっているオブジェクトがあるためです。これらのメソッドがなくOption、常にパターンマッチをオンにするか、isDefined頻繁に呼び出す必要がある場合、それらはほとんど役に立ちません。

代わりに、チェックされた例外はある程度の安全性を追加しますが、それらをキャッチするか、スタックをバブルさせる(タイプ宣言に追加されたボイラープレートを使用する)以外に、それらを使用してできることはあまりありません。


1
チェック例外は、多かれ少なかれ、同じ方法で構成する...との違いtry {/* bunch of complex code involving calls to 50 different methods that may throw SomeCheckedException */} catch(SomeCheckedException e) {/* operation failed, do something */}とはfromMaybe someDefaultValue (something >>= otherThing >>= ...50 other functions that may return Nothing...)まさにですか?前者が何が間違っていたかの詳細を提供するという事実以外。
user253751

14

関連していますが、例外とMaybeオブジェクトは同じタイプの問題を処理しません。

例外

例外的な状況(場合によってはエラーになる)に非ローカルで対処する必要がある場合、例外は本当に輝いています。たとえば、csvを解析していて、間違ったフォーマットの行から保護したい場合。何かがおかしいとわかる場所は、行の繰り返しから離れた関数呼び出しかもしれません。最も深いレベルで例外をスローする場合(フォーマットの問題について調べる場所)、ループで例外をキャッチし、エラーをログに記録して、次の行に進むことができます。コードの残りの部分を変更する必要はありません。

すべての中間関数がスロー可能な型を宣言する必要があるため、チェック例外は多くの苦痛を追加します。この機能は元の目的に反しているため、最近では人気がありません。

たぶんオブジェクト

ローカルで「障害」に対処できる場合は、オブジェクトを選択する必要があります。その意味で、これらは戻りコード+参照渡しのapiまたはnull入力可能な型の代わりになります。

Maybeオブジェクトの利点は、何かが間違っている可能性があることを明示的に宣言できることです。haskellでは、非多分オブジェクトは値を持たなければなりません。そうでなければ、プログラムはコンパイルしません。

null許容型の問題は、絶対に安全であるために常にnullをチェックする必要があることです。「何かが間違っている可能性がある」状態がデフォルトです。

リターンコード+参照APIによるパスの問題は、ほとんどの人にとって読みにくいことです。


1
@MattFenwickフィードバックをありがとう。csvの例が意味をなさないと思うのはなぜですか?OPはボイラープレート回避手法を実際に要求しておらず、適用可能なファンクターやモナドなどの語彙はこの質問には技術的すぎるかもしれないと感じています。
サイモンベルゴ

1
Java(チェック済み例外のある他の言語は不明)では、IDEがスローの追加とプルーニング、およびjavadocコメントの定型部分の更新を処理します。したがって、少なくともその部分は面倒ではなく、確かに痛みもありません。APIの設計を行うときに、それが苦痛であれ、恩恵であれ、その間の何かであれ、それは別の問題です
...-hyde

5
@hyde:IDEが無意味なボイラープレート生成を自動化できるからといって、無意味なボイラープレートが苦痛ではないという意味ではありません。
マイケルショー

2
@hyde:しかし、痛みは取り除かれていません。無意味な定型文はまだそこにあり、理由もなくコードを乱雑にします。定型句の理由がある場合、それは何ですか?
マイケルショー

2
@MichaelShaw例外に意味がない場合は、それを削除します。状況を無視するか、代わりにエラー値を返します。バグまたは回復不可能な状況の場合:未確認の例外を使用します。残っているのは、無意味な定型文ではなく、パラメータの例のタイプと同じくらい重要です。既存のライブラリのAPIが悪い場合は、ラッパーメソッド/クラスを検討するか、別のライブラリを使用するか、単に悪いAPIに悩まされます。
ハイド

1

なぜなら Maybe実際に値が必要になるまでエラーの処理を遅らせることができるからです(数回のメソッド呼び出しが必要になる場合があります)

一方、チェック例外は呼び出し場所で処理する必要があります

例外の唯一の利点は、失敗した理由についてより多くの情報を渡すことができるということです(誰かがMaybeErrorエラーの場合にスロー可能なフィールドで開発しない限り)


2
しかし、メソッドがこの例外をスローすることを宣言することで、チェック済み例外の処理を延期できます。
マッドサイエンティスト

1
@MadScientistはコールスタックを上げるだけですが、多分すべての方向に進むことができます
ラチェットフリーク

5
Maybe型とエラー処理を混同しないでください。例外はエラーを報告するために使用され、オプションタイプは部分的な関数の結果を表すために使用されます。部分的な関数の戻りNothingはエラーではありません。
ジョルジオ

@MadScientist:メソッド呼び出しが「無効な値」の指示を返す場合、その直後のステートメントを実行できます。対照的に、メソッドがすぐにキャッチされない例外をスローする場合、呼び出しに続くステートメントはスキップされます。チェックされた例外を呼び出しスタックに浸透させることは、呼び出し元が条件が呼び出したメソッドによって期待される意味を持っているかどうかを知る方法がないため、一般的には悪意があります呼び出されたメソッドがバブルアップさせている予期しない状態を表しているかどうか。
supercat
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.