2017-04-01 15 views
2

これは抽象的な質問であり、実際のコードはありません(そしておそらく最善の疑似コードもありません)ので、うまくいけば、モデレートされて死に至らないほど意味があります。しかし、それは、私がやっているプロジェクトが以前の条件、プロセスに依存する非常に直線的なものであることから、何度も私に何度も出てきた質問です。だから...逐次的なロジックと可読性

それぞれが先行するものに依存する一連の論理タスクが与えられているので、私はコードを構造化する2つの方法を試みました。 一つは、この

Proceed = True 

If Task1 Not Successful Then 
    Proceed = False 
End If 

If Proceed Then 
    If Task2 Not Successful Then 
     Proceed = False 
    End If 
End If 

などのような

proceed変数に依存します。しかし、私は、この実行は、変数のアプローチは理想的ではないことを進ん効果に場所のコメントの数で読みました。だから、代わりに私は持っていることができます

If Task1 Succcesful Then 
    If Task2 Successful 
     Then Etc 
    Else 
     Error Condition 
    End If 
Else 
    Error Condition 
End If 

私の目には、前者はもっと読みやすく、論理は非常に明らかです。そして、シーケンス内のタスクの数が大きくなると(3つ以上の場合)、ネストされたIfは実際に扱いにくくなります。 私の質問は、この最初のアプローチを使用しない理由は何ですか? 2番目の例では、可読性を向上させるためにロジックを構成する方が良い方法はありますか? あるいは、前者の問題(それが何であれ)と後者の読みやすさの問題の両方に対処する3つ目の方法はありますか? または、実際に連続して依存するタスクのシーケンスを実際に持っている場合、最初のアプローチは実際には問題ありませんか?

答えて

0

本当にあなたの状況によって異なります。任意のさらなる詳細がなくて、そしてあなたの元のブロックと厳密に等価であるコードにこだわって、私は不必要なネストを回避することから始めます:

Proceed = False; 

if Task1 successful and Task2 successful Then 
    Proceed = True 
end if 

ほとんどの言語で、あなただけの変数にまっすぐブールを置くことができます。

Proceed = task1 successful and task2 successful 

あなたは本当に、おそらくこのようその後、回避したい場合:

Proceed = True; 

If Task1 not successful then 
    Proceed = False 
Else if Task2 not successful then 
    Proceed = False 
Else if Task3 not successful then 
    Proceed = False 
End if 

すべての場合において、これまでに、あなたはネスティング避けます。読みやすくするために、これは重要です。

これ以外にも、2つの変更点があります。まず、 "Proceed"変数が完全に削除されたという事実です。これに同意する。どのようなあなたの元のコードの読者は、克服しなければならないです:あなたが変更することができる場合、xはその後、yの準備を...さて、今

Yをすれば

は、今... Xを初期化しますこれに:

xがyの後、概念的に簡単です

行う場合。

だから私はどうなる:

If Task1 successful and Task2 successful and Task3 successful then 
    Do your thing 
End if 

それとも

If Task1 not successful then 
    Do something 
else If Task2 not successful then 
    Do some other thing 
else 
    Do your main thing 
end if 

2つ目の違いは、あなたが「エラー状態」に置くということです。特に、あなたは "エラー"と言います。読んでいる文書が、実行を停止してエラーメッセージを出力するなど、エラーを処理する必要があるとしている場合は、これが正しいです。チャンスがあれば、Task1プロシージャのようなif/thenステートメントに到達する前にそれらを処理する必要があります。これはif/thenステートメントを簡略化するだけでなく、コーダーの方が優れているため、適切なIDEがエラーにつながるため、エラーが発生したらすぐに処理することが最善です。開発者は、何が最終的な情報源であるかを見るために長い道のりがありません。

0

どちらも共通しています。いくつかの方法が順番に呼び出される必要があり、いくつかのコヒーレントAPIで作業するときに最初は特に一般的である:あなたが巣を超える2-3レベルを必要としない場合

API_THING *thing = NULL; 
API_RESULT result = CreateThing(&thing, ...); 
if (API_OK == result) result = InitializeThing(&thing, ...); 
if (API_OK == result) result = DoThingToThing(&thing, ...); 
// ... 
if (thing) 
{ 
    ReleaseThing(&thing, ...); 
    thing = NULL; 
} 

その他は共通である(特に深い場合どちらの場合も)が処理されます。

示唆されていないもう一つですgotoおよび/または例外:

API_THING *thing = NULL; 
if (API_OK != CreateThing(&thing, ...)) goto CLEANUP; 
if (API_OK != InitializeThing(&thing, ...)) goto CLEANUP; 
if (API_OK != DoThingToThing(&thing, ...)) goto CLEANUP; 
//... 
CLEANUP: 
if (thing) 
{ 
    ReleaseThing(&thing, ...); 
    thing = NULL; 
} 

場合は、上記のgotoの例のように行い、各ライン上に投げる可能性がある例外を使用して、またはあなたがmig HT投げる方法であなたのAPIをラップ:

void DoCreateThing(API_THING **thing, ...) 
{ 
    if (API_OK != CreateThing(thing, ...)) 
     throw new ApiException("CreateThing Failed!"); 
} 

//... 

API_THING *thing = NULL; 
try 
{ 
    DoCreateThing(&thing, ...); 
} 
catch (ApiException e) 
{ 
    // ... 
} 
// ... 
finally 
{ 
    if (thing) 
    { 
     ReleaseThing(&thing, ...); 
     thing = NULL; 
    } 
} 

は心を取る:あなたはプログラミングの権利を行っている場合、どのような決断ここで行うことは、あなたの高レベルのアーキテクチャから、行動のこのビットをカプセル化する方法と同様に重要ではありません。

関連する問題