かなり深くネストされたコードを書きました(あるとき、forloop内のforloop内の条件チェック内のforloop内の条件チェックである何かを書きました)。
ネストされたforループ/条件式の数の制限に関する一般的なガイドラインはありますか?
古典的なコードメトリックの1つである 循環的複雑度 に触れています。ネストされたレベルを測定するのではなく、ループと条件(通常、ネストされたレベルを囲む)を測定します。
[〜#〜] pmd [〜#〜] (a Java静的分析ツール)は、その指標の1つとして複雑さを持ち、 これは言うそれについて :
複雑さは、メソッドの決定点の数とメソッドエントリの決定点の数によって決まります。決定ポイントは、「if」、「while」、「for」、「caseラベル」です。一般に、1〜4は複雑度が低く、5〜7は中程度の複雑度、8〜10は高複雑度、11 +は非常に複雑度が高いことを示します。
参照 コードメトリックをバグ密度に関連付ける実験 P.SEから。これは、実際の測定にさらに深く入ります。
C言語では、最大127レベルのネストされたブロックを使用できます。 640KBのRAMのように、それだけで誰もが必要とするはずです。
実際には、4レベルまたは5レベルより深くネストしている場合は、それらの内部レベルのいくつかを独自の関数に分解することを検討してください(またはアルゴリズムを再考してください)。他に何もなければ、コードのスキャンは簡単になります。
ネストされた構造についての抜粋であるRobert Martinによる"Clean Code"を読むことを強くお勧めします。
ブロックとインデント
...
if
ステートメント、else
ステートメント、while
ステートメントなどの中のブロックは、1行の長さである必要があります。おそらくその行は関数呼び出しでなければなりません。これにより、囲まれた関数が小さく保たれるだけでなく、ブロック内で呼び出された関数にわかりやすい名前を付けることができるため、記録的な価値が追加されます。関数はネストされた構造を保持するのに十分な大きさであってはならないであることも意味します。したがって、関数のインデントレベルは1または2以下にする必要があります。もちろん、これにより機能が読みやすくなり、理解しやすくなります。
したがって、Bob Martinの推奨はネストされた構造化の部は最大で2つである必要がありますです。
私はそれに同意し、常に遵守するわけではありませんが、少なくとも努力します。
また、静的分析ツールPDMのデフォルト構成によれば、関数の循環的複雑度は11を超えてはならず、2を超えると簡単に到達します。
コーディング標準に関するほとんどの質問と同様に、答えはコードを読みやすくするものです。
私はそれが通常ロジックの埋め込まれたゼロ層にかなり近いと主張します。しかし、そうではない場合もあり、常識に反するルールに熱心に固執することは、独自のコードを読み取る、または他の誰かにアクセスさせるという単純なポリシーを守るよりも有害です。
読みやすくするものなら何でも。
個人的には、1つの関数の4つまたは5つを超えるレベルを避けようとしています。それ以上は悪い「コードのにおい」でしょう。プログラムの構造を調整するか、問題を再定式化することで、それを回避することをお勧めします。
ネストされたループの欠点の1つはまだ言及されていません。各ループが大きなデータセットを反復処理する場合、アルゴリズムには非常に複雑なクラスが含まれます。例えば、
_foreach(foo in foos) {
foreach(bar in bars) {
foreach(baz in bazzes) {
foreach(buzz in buzzes) {
do_a_thing(foo, bar, baz, buzz);
}
}
}
}
_
foos
、bars
、bazzes
およびbuzzes
がすべてほぼ同じサイズであれば、おおよそO(n^4)
時間で実行されます。
コレクションが常に少なくなる場合、これは問題ではありません。次に、他の全員のアドバイスが適用されます。ただし、コレクションが1000以上のアイテムになる可能性が高い場合は、可能であれば、より高速なアルゴリズムを探すことをお勧めします。