深いインデントを防ぐ方法は?[閉まっている]


17

コードの深いインデントを防ぐために、どのような手順と対策を講じることができますか?


2
多くの人がここでリファクタリングについて話します。たぶんこれは質問するには多すぎるかもしれませんが、深くインデントされた(長すぎない)いくつかのコードを投稿すると、人々はそれをどのようにリファクタリングするかを示すことができます。もちろん、それはおそらく...その後、質問言語の特定を作る
Paddyslacker

3
より小さなタブ幅を使用してください。
ミパディ

6
矢印のアンチパターン。ヒントの負荷、それをGoogleに
NimChimpsky

2
Pythonの使用を停止:D
back2dos

制御ロジックとループロジックを見てみましょう。おそらくあなたのコードは必要以上に複雑であり、問​​題を再概念化するとコードはずっと短くなります。優れたコードを研究し、テクニックを学びます。
マクニール

回答:


14

プログラムのすべての関数/メソッドが1つだけのことを行う場合、通常、深いインデントは問題になりません。場合によっては、条件を数レベル深くネストする必要があるかもしれませんが、正直に言って、12年以上のコーディングの中で、深くインデントされたコードを数回しか書いたことはありません。


26

あなたができる最善のことは、メソッドを抽出することです:

int Step1(int state)
{
    if (state == 100)
    {
        return Step2(state);
    }
    else
    {
        return Step3(state);
    }
}

int Step2(int state)
{
    if (state != 100)
    {
        throw new InvalidStateException(2, state);
    }

    // ....
}

2
これは複雑なif条件でも機能します。極端に考えると、実行可能な疑似コードになります。
アランプラム

他にできる最善のことは、おそらく不要なelseブロックをドロップすることです。
セファー

16

たぶん、あなたはガード条項を考慮することができますか?

の代わりに

public void DoSomething(int value){
    if (someCondition){
           if(someOtherCondition){
                if(yetAnotherCondition){
                       //Finally execute some code
                }
           }
    }
} 

行う

public void DoSomething(int value){
    if(!(someCondition && someOtherCondition && yetAnotherCondition)){
        return;
        //Maybe throw exception if all preconditions must be true
    }
    //All preconditions are safe execute code
}

機会があれば、Steve McConnellのCode Completeを読むことをお勧めします。彼は、これらのトピックについて多くの素晴らしいアドバイスを受けています。

http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=pd_sim_b_6

「ガード条項」の詳細については、https//sourcemaking.com/refactoring/replace-nested-conditional-with-guard-clausesを参照してください。


8

を反転しますif

の代わりに:

if (foo != null)
{
    something;
    something;
    if (x)
    {        
       something;
    }
    something;
}
else
{
    boohoo;
}

私は書くだろう:

if (foo == null)
{
    boohoo;
    return;
}
something;
something;
if (x)
{        
   something;
}
something;

同じことがif- elseブロックにも当てはまります。elseが短い/ネストが少ない場合は、元に戻します。

パラメータの値を1か所で確認する

メソッドを入力したらすぐにすべてのパラメーターの不正な値を確認し、安全であることを確認してください。これにより、コードが読みやすくなりますが、後で条件ブロックを積み上げて、これらのチェックをサブルーチン全体に広げることもできます。


1
このスタイルには特定の名前がありますか?
トーマス・ローリア

@ThomasLauria私が知っていることではない。早く終了します。Ifいくつかの条件が満たされないために実行フローを停止するコードの先頭にある@JasonTuranが指摘したように、セーフガード句とも呼ばれます。そして、それは明確な名前を持つことに近づいているようです。
コンラッド・モラウスキー

数年前、私の監督者は、このスタイルは「線形プログラミング」と名付けられたと私に言ったが、これは彼の幻想だと思う;)
トーマス・ローリア

4

通常、深くインデントされたコードは通常、問題のあるコードであることがわかりました。この問題に直面している場合は、戻って、関数があまりにも多くのことを行っているかどうかを評価してください。

同時に、あなたの質問に答えるために、深くインデントする必要がある場合、そこに置くことをお勧めします。このようなコードでは、非常に長いコードになる可能性が高いため、インデントが役立つという単純な理由によります。


2

ネストされたコンポーネント(特に繰り返されるコンポーネント)を個別の関数に分割する(言語がクロージャーをサポートしている場合、これは簡単です)または一連のネストされたループを再帰で置き換えます。

また、4つではなく2つのスペースをインデントします。


5
タブの幅を変更するステップに
進むと

二つの空間のタブが....難しいものです
デヴィッド・ソーンリー

6
インデントを変更することは、解決策ではなく問題を非表示にする方法にすぎません
マーフ

1

深いインデントは、削除すべきカテゴリ別の問題ではありません(また、リファクタリングがすべての真の答えだとは思いません)。

通常、ネストされたifの代わりに、論理ステートメントを記述します。

if (foo && bar && baz) 

のではなく

if foo 
 if bar
   if baz

問題は、このルールに該当しないforおよびwhileループも存在することです。
タマラウィスマン

@TomWij:私はスタイルについてのカテゴリー的な命令を誘発しようとはしていません。
ポールネイサン

1
??? `` `` ``
タマラワイズマン

1

私はそれを信じていませんでしたが、Code Completeによれば、これは適切な場所ですbreak(チームが参加している場合)。ただし、ステートメントをbreak使用するC ++プログラマの方が、ループを作成したくない場合にのみ使用されるswitchDelphiプログラマの場合よりも、これが受け入れられるとbreak思いwhileます。


0

インデントは、実際に戦うために本当に考えています。私がすることを学んだことは、最初にメソッドを断片に分割し、次に奇妙なトリックを使用して、1つの断片が失敗した場合、後続のすべての断片をスキップすることです。以下に例を示します。

の代わりに :

 {if (networkCardIsOn() == true)
     {if (PingToServer() == true)
        {if (AccesLogin(login,pass) == true)
             {if (nextCondition == true)
                ...
         }
     }
 }

私は現在書いています:

 {vbContinue = true;

 if (vbContinue) {
       vbContinue = networkCardIsOn();
       if (vbContinue == false) {
             code to Handle This Error();
       } 
 }

 if (vbContinue) {
       vbContinue = PingToServer();
       if (vbContinue == false) {
             code to HandleThisError2();
       } 
 }

 if (vbContinue) {
       vbContinue = AccesLogin(login,pass);
      if (vbContinue == false) {
             HandleThisErrorToo();
       } 
 }
 ...

これは最初は奇妙に思えますが、これを使用するため、メンテナンスコストが半分に分割され、1日の終わりに脳が冷たくなります。

実際、この「テクニック」によってもたらされる利点は、コードの密度が低いため、コードの複雑さが実際に分割されることです。

コードを読んでいる間、過去の条件について何も覚えておく必要はありません。コードのそのポイントXにいる場合、前のステップはパスして成功しています。

もう1つの利点は、ネストされたすべての「if-else」からの「エスケープパスと条件」が単純化されることです。


「メンテナンスコストが半分になった」ことについて詳しく説明してください
クリス

編集しました。私はあなたの質問に答えることを願っています...
ピエールワトレ

2
単純に行きたい場合は、goto error_handling行があります。
ポールネイサン

イケてないよ。申し訳ありませんが、そうではありません。その後、再び私は奇妙です
マーフ

3
try catchをエミュレートする代わりに、直接使用しないのはなぜですか?
ニュートピア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.