web-dev-qa-db-ja.com

ネストされたifステートメントの置換

これは beautiful code の章に関連しています。そしてその章では、ネストされたifsについて読みました。

作者は、深くネストされたifsをバグの発生源として読みやすくしていました。そして、彼はネストされたifsをcaseステートメントと 判定テーブル で置き換えることについて話していました。

ネストされたifsをcaseselect case)および決定表

28
Biswanath

まあ、具体的にswitch/caseステートメントについて尋ねるので、あなたの質問への直接的な答えではありませんが、同様の質問があります。

ネストを減らすために「if」ステートメントを反転

これは、ネストされたifを、戻り値に落ち着く前に徐々にチェックするのではなく、早期に戻るガードステートメントで置き換えることについて説明しています。

私がいつもやろうとする1つの例は、次のような重いネストを置き換えることです(実際、これはtooではありませんが、私はそれらを最大8または9レベルの深さで見ました):

if (i == 1) {
    // action 1
} else {
    if (i == 2) {
        // action 2
    } else {
        if (i == 3) {
            // action 3
        } else {
            // action 4
        }
    }
}

これとともに:

switch (i) {
    case 1:
        // action 1
        break;
    case 2:
        // action 2
        break;
    case 3:
        // action 3
        break;
    default:
        // action 4
        break;
}

また、アクションを可能な限り小さくして(関数呼び出しが最適です)、switchステートメントを圧縮したままにします(そのため、4ページ先に移動して終了を確認する必要はありません)。

決定テーブルは、後で実行する必要があるアクションを示すフラグを設定するだけです。 「後で」セクションは、これらのフラグに基づいたアクションの単純なシーケンスです。私は間違っている可能性があります(初めてでも最後でもありません:-)。

例は次のとおりです(フラグ設定フェーズは、アクションが非常に単純なので、ifが複雑になる場合があります)。

switch (i) {
    case 1:
        outmsg = "no paper";
        genmsg = true;
        mailmsg = true;
        phonemsg = false;
        break;
    case 2:
        outmsg = "no ink";
        genmsg = true;
        mailmsg = true;
        phonemsg = false;
        break;
    default:
        outmsg = "unknown problem";
        genmsg = true;
        mailmsg = true;
        phonemsg = true;
        break;
}

if (genmsg)
    // Send message to screen.
if (mailmsg)
    // Send message to operators email address.
if (phonemsg)
    // Hassle operators mobile phone.
10
paxdiablo

連鎖ifはどうですか?

交換

if (condition1)
{
    do1
}   
else
{
    if (condition2)
    {
        do2
    }
    else (condition3)
    {
        do3;

    }
}

if (condition1) {
   do1;
} else if (condition2) {
   do2;
} else if (condition3) {
   do3;
}

これは、複雑な条件のswitchステートメントによく似ています。

9
Arkadiy

条件をブール値にしてから、各ケースにブール式を記述します。

コードが次の場合:

if (condition1)
{
    do1
}   
else
{
    if (condition2)
    {
        do2
    }
    else (condition3)
    {
        do3;

    }
}

次のように書くことができます:

bool cond1=condition1;
bool cond2=condition2;
bool cond3=condition3;

if (cond1) {do1;}
if (!cond1 and cond2) {do2;}
if (!cond1 and cond3) {do2;}
6
khivi

決定表については、 この質問 への私の答えをご覧ください。または、 コード完了2 の第18章をお読みください。

3
Yuval F

たとえば、検証の一部が失敗した場合にブレークできます。

function validate(){
  if(b=="" || b==null){
      alert("Please enter your city");
      return false;
  }

  if(a=="" || a==null){
      alert("Please enter your address");
      return false;
  }
  return true;
}
2
Alexis Paques

決定テーブルでは、コード自体ではなくデータ構造に条件付きロジックを保存しますを使用します。

したがって、これの代わりに(@Paxの例を使用して):

if (i == 1) {
    // action 1
} else {
    if (i == 2) {
        // action 2
    } else {
        if (i == 3) {
            // action 3
        } else {
            // action 4
        }
    }
}

あなたはこのようなことをします:

void action1()
{
    // action 1
}

void action2()
{
    // action 2
}

void action3()
{
    // action 3
}

void action4()
{
    // action 4
}

#define NUM_ACTIONS 4

// Create array of function pointers for each allowed value of i
void (*actions[NUM_ACTIONS])() = { NULL, action1, action2, action3 }

// And now in the body of a function somewhere...
if ((i < NUM_ACTIONS) && actions[i])
    actions[i]();
else
    action4();

iの可能性が小さい番号の整数でない場合、i配列のactionsth要素に直接アクセスする代わりに、ルックアップテーブルを作成できます。

この手法は、多数の可能な値を決定するときに、ネストされたifsまたはswitchステートメントよりもはるかに便利になります。

1
Paul Stephenson

Ifおよびswitchステートメントは純粋にオブジェクト指向ではありません。それらは条件付き手続き論理ですが、非常に良い仕事をします!より多くのOOアプローチのためにこれらのステートメントを削除したい場合、 'State'パターンと 'Descriptor'パターンを組み合わせてください

0

Visitor pattern の使用を検討することもできます。

0
Drejc

論理演算子ANDと同等の場合はネストされます

if (condition1)
{
    if (function(2))
    {
        if (condition3)
        {
            // do something
        }
    }
}

同等のコード:

if (condition1 && function(2) && condition3)
{
    // do something
}

どちらの場合も、式が偽と評価されると、後続の式は評価されません。たとえば、condition1がfalseの場合、function()は呼び出されず、condition3は評価されません。

0
Demis Palma ツ