@JackAidley はその要点をすでに述べていると思いますが、次のように定式化させてください。
例外なし(Cなど)
通常のコードフローには、次のものがあります。
if (condition) {
statement;
} else if (less_likely_condition) {
less_likely_statement;
} else {
least_likely_statement;
}
more_statements;
「早期エラーアウト」の場合、コードは突然読み取ります。
/* demonstration example, do NOT code like this */
if (condition) {
statement;
} else {
error_handling;
return;
}
あなたはこのパターンを見つけた場合- return
にelse
(あるいはif
問題のコードがないので)ブロック、すぐにそれを手直ししませ持つelse
ブロックを:
/* only code like this at University, to please structured programming professors */
function foo {
if (condition) {
lots_of_statements;
}
return;
}
現実世界では…
/* code like this instead */
if (!condition) {
error_handling;
return;
}
lots_of_statements;
これは、あまりにも深くネスト回避し、「早期抜け出す」の場合を満たして(心を維持するのに役立ちます-と、コードの流れ-クリーン)と「に可能性が高いものを入れ違反しないif
だけで何も存在しないため、一部」else
の部分は、 。
C
そしてクリーンアップ
同様の質問(これは間違っていました)の答えに触発され、Cでクリーンアップを行う方法を次に示します。1つまたは2つの出口ポイントを使用できます。2つの出口ポイントに1つあります。
struct foo *
alloc_and_init(size_t arg1, int arg2)
{
struct foo *res;
if (!(res = calloc(sizeof(struct foo), 1)))
return (NULL);
if (foo_init1(res, arg1))
goto err;
res.arg1_inited = true;
if (foo_init2(&(res->blah), arg2))
goto err;
foo_init_complete(res);
return (res);
err:
/* safe because we use calloc and false == 0 */
if (res.arg1_inited)
foo_dispose1(res);
free(res);
return (NULL);
}
実行するクリーンアップが少ない場合は、それらを1つの終了ポイントにまとめることができます。
char *
NULL_safe_strdup(const char *arg)
{
char *res = NULL;
if (arg == NULL)
goto out;
/* imagine more lines here */
res = strdup(arg);
out:
return (res);
}
goto
あなたがそれに対処することができれば、この使用はまったく問題ありません。使用を中止するためのアドバイスgoto
は、使用が良い、許容できる、悪い、スパゲッティコード、または他の何かであるかどうかをまだ自分で決定できない人々に向けられています。
例外
上記は例外のない言語について語っていますが、私はそれを非常に好みます(明示的なエラー処理をはるかに優れた方法で使用でき、驚きも少なくなります)。igliを引用するには:
<igli> exceptions: a truly awful implementation of quite a nice idea.
<igli> just about the worst way you could do something like that, afaic.
<igli> it's like anti-design.
<mirabilos> that too… may I quote you on that?
<igli> sure, tho i doubt anyone will listen ;)
しかし、例外のある言語でそれをうまく行う方法と、それらをうまく使用したい場合の提案があります:
例外が発生した場合のエラー戻り
Earlyのほとんどをreturn
例外をスローするように置き換えることができます。しかし、あなたの通常のプログラムの流れは、つまりプログラムが遭遇しなかったで任意のコードの流れ、よく、例外...エラー条件やsomesuch、してはならない任意の例外を発生させます。
この意味は…
# this page is only available to logged-in users
if not isLoggedIn():
# this is Python 2.5 style; insert your favourite raise/throw here
raise "eh?"
…大丈夫ですが、…
/* do not code like this! */
try {
openFile(xyz, "rw");
} catch (LockedException e) {
return "file is locked";
}
closeFile(xyz);
return "file is not locked";
…ではありません。基本的に、例外は制御フロー要素ではありません。これにより、Operationsが奇妙に見え(「Java™プログラマーは常にこれらの例外は正常であると言う」)、デバッグを妨げる可能性があります(たとえば、例外を発生させるだけでIDEに指示する)。多くの場合、例外を発生させるには、ランタイム環境でスタックをアンワインドしてトレースバックなどを生成する必要があります。これにはおそらく、さらに多くの理由があります。
つまり、例外をサポートする言語では、既存のロジックとスタイルに一致し、自然に感じるものを使用します。ゼロから何かを書く場合は、早めに合意してください。ライブラリをゼロから作成する場合は、消費者について考えてください。(abort()
ライブラリでも使用しないでください...)しかし、あなたがすることは何でも、原則として、操作がその後(通常)継続する場合、例外はスローされません。
一般的なアドバイス 例外
まず、開発チーム全体で合意された例外のすべてのプログラム内使用を取得してください。基本的に、それらを計画します。それらを豊富に使用しないでください。場合によっては、C ++、Java™、Pythonでさえ、エラーが返される方が良い場合があります。時々そうではありません。それらを考えて使用してください。