Javaのチェック済み例外は、長年にわたっていくつかの悪い報道を受けてきました。兆候は、それが文字通り世界で唯一の言語であることです(GroovyやScalaなどの他のJVM言語でさえも)。著名なJavaライブラリもそれらを使用しません。
私は個人的にそれらの1つの使用法を見つけました( ビジネスロジックでは レイヤー間)が、それ以外の場合はかなりチェックされていない例外です。
他に気づかない使い方はありますか?
まず、他のプログラミングパラダイムと同様に、正しく機能させるには、それを正しく実行する必要があります。
meの場合、チェック例外の利点は、Javaランタイムライブラリの作成者が、私が処理できると合理的に期待できる一般的な問題をすでに決定していることです。 callingポイントで(トップレベルのcatch-print-dieブロックとは対照的に)、これらの問題を処理する方法をできるだけ早く検討します。
チェック例外は、エラー回復についてできるだけ早く考えるように強制することでコードをより堅牢にするため、チェック例外が好きです。
より正確に言うと、meを使用すると、コードがより堅牢になります。「おっと、ファイルが処理しない場合、コードは処理されません。まだ存在していない」というのは、本番環境でのエラーに基づいており、処理するためにコードを作り直す必要があります。既存のコードにエラー処理を追加することは、最初からすぐに行うのではなく、メンテナンスに到達するときに、重要なタスクになる可能性があり、したがってコストがかかります。
不足しているファイルは致命的なものであり、プログラムが炎上でクラッシュする可能性がありますが、yoでその決定を行います
} catch (FileNotFoundException e) {
throw new RuntimeException("Important file not present", e);
}
これは非常に重要な副作用も示しています。例外をラップする場合、stack-traceに入る!という説明を追加できます。これに関する情報を追加できるため、これは非常に強力です。欠落していたファイルの名前、またはこのメソッドに渡されたパラメーターまたはその他の診断情報、およびその情報が存在するスタックトレースの右側これは、プログラムが持っているときに頻繁に取得される単一の情報です。クラッシュしました。
人々は「デバッガでこれを実行して再現できる」と言うかもしれませんが、非常に頻繁に生産エラー再現不可が後であり、非常に厄介な場合を除いて、生産でデバッガを実行できないことがわかりました基本的にあなたの仕事が危機に瀕しています。
スタックトレースに含まれる情報が多いほど、優れています。チェック例外は、その情報をそこに、そして早期に取得するのに役立ちます。
編集:これは、ライブラリデザイナーにも当てはまります。私が日常的に使用する1つのライブラリーには、多数のチェック済み例外が含まれています。
チェック例外が実際にどのようになったかを説明する2つの良い答えがあります。 (+1と両方。)しかし、意図が実際に価値があるので、理論上それらが意図されていたものを調べることも価値があります。
チェック例外は、実際には言語をよりタイプセーフにすることを目的としています。整数乗算のような簡単な方法を考えてみましょう。このメソッドの結果の型は整数であると考えるかもしれませんが、厳密に言えば、結果は整数またはオーバーフロー例外のいずれかです。メソッドの戻り値の型として整数の結果を単独で考慮しても、関数の全範囲を表すわけではありません。
この観点から見ると、チェックされた例外が他の言語に反映されていないというのは厳密には正しくありません。これらは、Java使用される形式ではありません。Haskellアプリケーションでは、代数的データ型を使用して、関数の正常終了と異常終了を区別するのが一般的です。これは例外ではありませんが、それ自体、意図はチェック例外と非常に同じです。これは、APIコンシューマに、失敗した場合の両方の成功を処理するように強制するように設計されたAPIです。例:
data Foo a =
Success a
| DidNotWorkBecauseOfA
| DidNotWorkBecauseOfB
これにより、関数には成功以外に2つの結果が考えられます。
IMO、チェックされた例外は、mightがかなりまともなアイデアである(完全に異なる状況下では-しかし、現在の状況では本当に良いアイデアでもない)の欠陥のある実装です状況)。
プログラムがスローする可能性のあるすべての例外がキャッチされることをコンパイラーに検証させるのは良いことです。 Javaは、これを行うために、チェックされた例外をスローするように宣言されているものを呼び出すクラスで例外を直接処理することを強制します。最も基本的なアイデア(および利点)の1つです。例外処理の1つは、エラーが発生した場合、特定のエラーとは何の関係もないコードの中間層がその存在を完全に無視できるようにすることです。チェックされた例外(Javaで実装されている)はそれを許可しないため、破壊されますまず、例外処理の主要な(主要な?)利点です。
理論的には、チェック例外をプログラム全体でのみ適用することで、チェック例外を有効にすることができます。つまり、プログラムの「構築」中に、プログラムのすべての制御パスのツリーを構築します。ツリー内のさまざまなノードには、1)生成できる例外、および2)キャッチできる例外の注釈が付けられます。プログラムが正しいことを確認するには、次にツリーをウォークして、ツリーの任意のレベルでスローされたすべての例外がツリーのより高いレベルでキャッチされたことを確認します。
彼らが/しなかった理由は(とにかく)そうするのは非常に難しいためです-実際、誰かがビルドシステムを書いたとは思えませんextremelysimple( "toy"の境界)言語/システム以外のすべてに対してそれを行うことができます。 Javaの場合、動的クラスローディングのようなものは、他の多くの場合よりもさらに困難になります。さらに悪いことに、(Cのようなものとは異なり)Javaは(少なくとも通常は)実行可能ファイルに静的にコンパイル/リンクされていません。つまり、システム内の何も実際にグローバルな認識を持っていないことを意味しますtryエンドユーザーが実際にプログラムのロードを開始して実行するまで、この種の強制を実行します。
その時点で強制を行うことは、いくつかの理由で非現実的です。まず第一に、せいぜいJavaについての最大かつ最も一般的な不満の1つである起動時間を延ばすことさえあります。第2に、多くのことを行うには、プログラマーが問題を修正するのに十分早く、問題を本当に検出する必要があります。ユーザーがプログラムをロードしているとき、多くのことを行うには遅すぎます。その時点での唯一の選択肢は、問題を無視するか、プログラムのロード/実行を拒否することです。ただし、mightキャッチされなかった例外である。
現状では、チェックされた例外は役に立たないよりも悪いですが、チェックされた例外の代替設計はさらに悪いです。チェックされた例外の基本的な考え方は良いように見えますが、実際にはあまり良くなく、たまたまparticularlyはJavaにはあまり適していません。 C++のようなもので、通常は完全な実行可能ファイルにコンパイル/リンクされており、リフレクション/動的クラスロードとほとんど同じですが、正直なところ、同じ種類の混乱なしにそれらを正しく適用する可能性があります。現在Javaが原因でおそらくまだ現在の最新技術を超えているでしょう)。
プログラマーを悩ませたり、例外的な飲み込みを促したりするのに本当に便利です。例外の半分は、エラーを処理する適切なデフォルトの方法があり、処理できないエラー条件を明示的に伝播することを考える必要がないようにするためです。 (正気なデフォルトは、コード内のどこでもエラーを処理したことがない場合、それが発生しないことを効果的に主張し、間違っている場合は正気な出口とスタックトレースが残ることです。)チェックされた例外の敗北この。 Cで明示的にエラーを伝達する必要があるように感じます。
チェック例外は少し失敗した実験であったと言っても差し支えないと思います。彼らが間違っていたのは、彼らがレイヤーを壊したということです:
AとCに限定されていた可能性のあるエラーの知識をBに分散させる必要があるため、問題のニース分離は壊れています。
ウィキペディアにチェック済み例外の 素敵な議論 があります。
そして、ブルース・エッケルにも 素敵な記事 が載っています。ここに引用があります:
[T]プログラマーに積み重ねるランダムな規則が増えます。目の前の問題の解決とは何の関係もない規則ほど、プログラマーが生成する速度は遅くなります。そして、これは線形因子ではないように見えますが、指数関数的です
C++の場合は、すべてのメソッドにthrows
仕様句がある場合は、いくつかの最適化を行うことができます。 Javaとにかくこれらの利点があるとは思いませんが、RuntimeExceptions
がチェックされていないためです。現代のJITはとにかくコードを最適化できるはずです。
AspectJの優れた機能の1つは、例外の軟化です。特にレイヤー化を強化するために、チェックされた例外をチェックされていない例外に変換できます。
Javaが代わりにnull
をチェックできたときに、この問題をすべて解決したのは皮肉なことかもしれませんが、 貴重な 。
例外が大好きです。
しかし、私はそれらの誤用に常に困惑しています。
フロー処理に使用しないでください。例外はオブジェクトを作成する必要があり、メモリなどを使用する必要があるため、例外を作成する必要があるオブジェクトであるため、例外をトリガーとして使用して、何かを実行するコードは必要ありません。呼び出しの前に、一種のif()チェックを行います。それは単に怠惰であり、栄光の例外に悪い名前を与えます。
それらを飲み込まないでください。ずっと。どんな状況下でも。絶対に最低限、ログファイルに何かを貼り付けて、例外が発生したことを示します。例外を飲み込むコードをたどって追跡するのは悪夢です。繰り返しになりますが、強力な例外を不名誉なものにしてしまったために、例外を飲み込む人を呪います!
例外を自分のOOハットで処理します。意味のある階層を持つ独自の例外オブジェクトを作成します。ビジネスロジックと例外を連携させて階層化します。新しい領域から始めたら、システムの場合、コーディングから30分以内にExceptionをサブクラス化する必要があるので、最近はExceptionクラスを作成することから始めます。
コードの「フレームワーク」ビットを記述している場合は、すべての初期インターフェイスが適切な場所で独自の新しい例外をスローするように記述されていることを確認してください...そして、コーダーがコードを実行するときに、何をするかについて、コードのサンプルコードを確認してください。 IOExceptionをスローしますが、書き込み先のインターフェイスが 'ReportingApplicationException'をスローしようとしています。
例外を機能させる方法を理解したら、決して振り返ることはありません。
チェック例外もADAにあります。
(警告、この投稿には、あなたが直面している可能性があると強く信じられている信念が含まれています。)
プログラマはそれらを気に入らず文句を言うか、例外を飲み込むコードを書きます。
チェックされた例外が存在するのは、物事が機能しないだけでなく、故障モード/影響分析を実行して、これを事前に判断できるためです。
ファイルの読み取りが失敗する可能性があります。 RPC呼び出しが失敗する可能性があります。ネットワークIO失敗する可能性があります。解析時にデータのフォーマットが誤っている可能性があります。
コードの「ハッピーパス」は簡単です。
私は、すばらしい「ハッピーパス」コードを書くことができる大学の人を知っていました。 Edgeのケースはどれも機能しませんでした。最近、彼はPython=オープンソース企業向けに)しています。
チェックされた例外を処理したくない場合、あなたが本当に言っていることは
While I'm writing this code, I don't want to consider obvious failure modes.
The User will just have to like the program crashing or doing weird things.
But that's okay with me because
I'm so much more important than the people who will have to use the software
in the real, messy, error-prone world.
After all, I write the code once, you use it all day long.
したがって、チェックされた例外は、より多くの作業を意味するため、プログラマーに好かれることはありません。
もちろん、他の人々はその仕事をしてほしかったかもしれません。
ファイルサーバーに障害が発生した場合やUSBスティックが停止した場合でも、正しい回答が必要だった可能性があります。
あなたの仕事がソフトウェアを書くことであるとき、あなたがあなたの人生をより楽にして、楽しくするプログラミング言語を使うべきであるというのは、プログラミングコミュニティの奇妙な信念です。あなたの仕事は誰かの問題を解決することであり、プログラマティックジャズの即興に従事させることはできません。
あなたがアマチュアプログラマー(お金のかかるプログラミングではない)の場合は、C#またはその他の言語で、チェックされた例外なしで自由にプログラミングしてください。一体、中間者とプログラムをロゴで切り取ります。カメと一緒に可愛いパターンを床に描くことができます。
チェックされた例外は、ソースに近いエラーを処理するように人々を励ますべきでした。ソースから離れるほど、実行中に終了する機能が増え、システムが不整合な状態になる可能性が高くなります。さらに、誤って誤った例外をキャッチする可能性が高くなります。
悲しいことに、人々は例外を無視するか、増え続けるスロー仕様を追加する傾向があります。これらはどちらも、チェックされた例外が奨励すると想定されている点を外しています。これは、手続き型コードを変換して、オブジェクト指向にする多くのGetter関数とSetter関数を使用するようなものです。
基本的に、チェックされた例外は、コードがある程度正確であることを証明しようとしています。コードが実行される前に特定のものが正しいことを証明しようとする点で、静的型付けとほとんど同じです。問題は、その追加証明のすべてに労力がかかり、その努力に価値があるということです。