私はそれについて考え、例を思い付くことができませんでした。なぜ誰かが例外をキャッチし、それについて何もしたくないのでしょうか?例を挙げていただけますか?たぶんそれは決してやるべきではない何かです。
私はそれについて考え、例を思い付くことができませんでした。なぜ誰かが例外をキャッチし、それについて何もしたくないのでしょうか?例を挙げていただけますか?たぶんそれは決してやるべきではない何かです。
回答:
私はいつもDの変換エラーのようなことでそれをしています:
import std.conv, std.stdio, std.exception;
void main(string[] args) {
enforce(args.length > 1, "Usage: foo.exe filename");
double[] nums;
// Process a text file with one number per line into an array of doubles,
// ignoring any malformed lines.
foreach(line; File(args[1]).byLine()) {
try {
nums ~= to!double(line);
} catch(ConvError) {
// Ignore malformed lines.
}
}
// Do stuff with nums.
}
とはいえ、例外を無視している理由を説明する単なるコメントであっても、すべてのcatchブロックに何かが含まれている必要があると思います。
編集:また、このようなことをする場合は、無視したい特定の例外のみをキャッチするように注意する必要があることを強調したいと思います。昔ながらのことをすることcatch {}
は、ほとんど常に悪いことです。
何もせず、例外を記録するだけで例外を飲み込むことができると私が思う一例は、コード自体を記録することです。
何かをログに記録しようとして例外が発生した場合、それに対してできることはあまりありません。
これにより、アプリケーションがメインジョブを実行し続けることができますが、それをトラブルシューティングする機能を損なう「静かに飲み込む」オプションが残ります。
とにかくオプションであった操作によって例外がスローされた場合、何もする必要はありません。ログに記録しても役に立たない場合があります。その場合、あなたはそれを捕まえて何もしないことを望むかもしれません。
これを行う場合は、コメントを含めてください。バグのように見えるものは常にコメントしてswitch
ください(ステートメント内のフォールスルー、空のcatch
ブロック、条件内の割り当て)。
これは例外の適切な使用法ではないと主張するかもしれませんが、それは別の質問です。
空のcatch
ブロックは、ほとんどの言語でコードの匂いがします。主なアイデアは、例外を例外的な状況に使用し、例外を論理制御に使用しないことです。すべての例外はどこかで処理する必要があります。
このアプローチを採用した結果、特定のアプリケーション層をプログラムする場合、いくつかの選択肢があります。
これは、何もしない、空のcatch
ブロックの余地を実際に残しません。
追加の編集:例外をスローすることが通常のプログラムロジックの制御方法である言語でプログラミングしているとします(の代替手段の1つgoto
)。そして、空catch
、この言語で書かれたプログラムでのブロックは非常に多くの空のようなものでelse
、伝統的な言語(または全く内のブロックelse
のすべてのブロック)。ただし、これはC#、Java、またはC ++開発コミュニティが推奨するプログラミングスタイルではないと考えています。
場合によっては、Javaでは、絶対にまったく発生することのない例外を処理する必要があります。次のコードを検討してください。
try {
bytes[] hw = "Hello World".getBytes("UTF-8");
}
catch(UnsupportedCodingException e) {
}
Javaプラットフォームのすべての実装は、次の標準文字セットをサポートする必要があります。
...
UTF-8
Javaプラットフォームを壊さなければ、この例外を引き起こす方法はありません。なぜそれを処理するのが面倒なのでしょうか?ただし、try-catch-clauseを単純に省略することはできません。
throw new Error(e)
、私は何も見逃さない(または実際に壊れたプラットフォームを報告する)ことを絶対に確実にするためだけに追加したくなるでしょう。
原則として、いいえ。スタックに例外をスローするか、何が起こったのかを記録する必要があります。
ただし、文字列を解析して数値に変換するときに、これをよく行います(特に、一度だけ使用してさまざまなものを捨てるマッピングプロジェクトの場合)。
boolean isNonZeroNumber = false;
try {
if(StringUtils.isNotBlank(s) && new BigDecimal(s).compareTo(BigDecimal.ZERO) != 0) {
b = true;
}
} catch(NumberFormatException e) {
//swallow this exception; b stays false.
}
return b;
場合によっては、例外はまったく例外ではありません。実際、期待されています。この例を考えてみましょう:
/* Check if the process is still alive; exitValue() throws an exception if it is */
try {
p.exitValue();
processPool.remove(p);
}
catch (IllegalThreadStateException e) { /* expected behaviour */ }
java.lang.Process()にはisAlive()メソッドがないため、まだ生きているかどうかを確認する唯一の方法は、exitValue()を呼び出すことです。これは、プロセスがまだ実行中の場合、IllegalThreadStateExceptionをスローします。
私の謙虚な経験では、めったにこの良いことはありません。ただし、走行距離は異なる場合があります。
コードベースでこれを見るたびに、それは食べられた例外が隠されているバグを追跡したからです。別の言い方をすれば、コードを提供しないことにより、アプリケーションにはエラーを示す方法や別のアクションを実行する方法がありません。
たとえば、APIレイヤーでは、例外を過去に通過させたくない場合があります。そのため、その場合は、最も一般的なものをキャッチしてログに記録する傾向があります。もう一度、少なくともデバッグ/診断セッションにチャンスを与えるために。
通常、空にする必要がある場合は、少なくとも何らかのアサーションを追加するだけなので、デバッグセッション中に少なくとも何かが発生します。つまり、処理できない場合は、完全に省略しがちです。
IMOには、空のcatchステートメントを使用できる場所が1つあります。例外が予想されるテストケースの場合:
try
{
DoSomething(); //This should throw exception if everything works well
Assert.Fail('Expected exception was not thrown');
}
catch(<whatever exception>)
{
//Expected to get here
}
例外が発生したときに何らかのレベルの警告が出ないとは思わない-プログラミングの目標の1つはコードを改善することではないでしょうか?例外が10%の時間で発生し、それを知らない場合、例外は常にそれほど悪いか、悪いことになります。
ただし、例外がコードの処理に実際の害を及ぼさない場合、なぜユーザーを例外にさらすのかという反対側を見ます。私が通常実装するソリューションは、ロガークラスによってログに記録することです(つまり、職場で書いたすべてのクラスにあります)。
良性の例外である場合は、Loggerの.Debug()メソッドを呼び出します。それ以外の場合、Logger.Error()(および(おそらく)スロー)。
try
{
doWork();
}
catch(BenignException x)
{
_log.Debug("Error doing work: " + x.Message);
}
ちなみに、ロガーの実装では、.Debug()メソッドを呼び出すと、App.Configファイルでプログラム実行ログレベルがデバッグモードになっている場合にのみログが記録されます。
存在チェックは良いユースケースです:
// If an exception happens, it doesn't matter. Log the initial value or the new value
function logId(person) {
let id = 'No ID';
try {
id = person.data.id;
} catch {}
console.log(id);
}
別のケースは、finally
句が使用される場合です。
function getter(obj){}
function objChecker()
{
try
{
/* Check argument length and constructor type */
if (getter.length === 1 && getter.constructor === Function)
{
console.log("Correct implementation");
return true;
}
else
{
console.log("Wrong implementation");
return false;
}
}
catch(e)
{
}
finally
{
console.log(JSON.stringify(getter))
}
}
// Test the override of the getter method
getter = getter;
objChecker();
getter = [];
objChecker();
getter = {};
objChecker();
getter = RegExp;
objChecker();
getter = Function;
objChecker();
これと同様のユースケースに関連するECMAScript のcatchバインディングの省略を許可する提案があります。
参照資料
このようなことを本当にする必要があったのは、コンソールアプリのログクラスを使用するときだけでした。最上位のグローバルキャッチハンドラーがあり、STDOUTにエラーを出力し、エラーをファイルに記録し、> 0のエラーコードでアプリを閉じました。
ここでの問題は、時々、ファイルへのロギングが失敗することでした。ディレクトリのアクセス許可により、ファイルの書き込みが停止され、ファイルは何でも排他的にロックされました。それが発生した場合、例外の詳細を記録するとロガーが同じアクションを実行するため、他の場所と同じ方法で例外を処理できませんでした(キャッチ、関連する詳細を記録、より良い例外タイプでラップなど)既に失敗したファイルに書き込もうとしています)。彼らが再び失敗したとき...あなたは私がどこへ行くのかを見る。無限ループに入ります。
try {}ブロックの一部をドロップすると、メッセージボックスに表示される例外で終わる可能性があります(サイレント構成アプリに必要なものではありません)。したがって、ログファイルに書き込むメソッドには、空のcatchハンドラがあります。エラーコードが0を超えているため、エラーは埋められません。無限ループが停止するだけで、アプリを正常に終了できます。
もちろん、なぜ空なのかを説明するコメントがあります。
(これを以前に投稿するつもりだったので、私は忘却に火が付くのをただ恐れていました。しかし、私だけではないので...)
最後に配置された最も重要なピースが何であれ、何らかのシーケンスを実行する必要がある場合は問題ありません。
例えば。ホストからコントローラーへのモーションコントロール通信。緊急の状況では、移動を中止し、軌道生成を停止し、モーターを減速し、ブレークを有効にし、アンプを無効にするための準備ステップがいくつかあります。その後、バスパワーを停止する必要があります。すべては順番に実行する必要があり、ステップの1つが失敗した場合、ハードウェアを損傷するリスクが認められていても、残りのステップを実行する必要があります。上記のすべてが失敗したとしても、とにかくバスのキルパワーが発生する必要があるとしましょう。
システムリソースを正常に閉じてエラーから回復する
例えば。ユーザーにフィードバックを提供しないサービスをバックグラウンドで実行している場合、エラーの表示をユーザーにプッシュしたくない場合がありますが、使用されているリソースを適切に閉じる必要があります。
try
{
// execution code here
}
catch(Exception e)
{
// do nothing here
}
finally
{
// close db connection
// close file io resource
// close memory stream
// etc...
}
理想的には、デバッグモードでcatchを使用してエラーをキャッチし、テスト用にコンソールまたはログファイルに出力します。実稼働環境では、一般に、エラーがスローされたときにバックグラウンドサービスがユーザーを中断しないことが期待されるため、エラー出力を抑制する必要があります。