I’ve written some code that has some fairly deep nests (one time, I wrote something that was a conditional check inside a forloop inside a conditional check inside a forloop inside a forloop).
Is there a general guideline on limits to the number of nested for loops/conditionals you have?
4
You are touching upon one of the classic code metrics – cyclomatic complexity. It doesn’t measure nested levels, but rather loops and conditionals (which typically enclose nested levels).
PMD (a Java static analysis tool) has complexity as one of its measures and has this to say about it:
Complexity is determined by the number of decision points in a method plus one for the method entry. The decision points are ‘if’, ‘while’, ‘for’, and ‘case labels’. Generally, 1-4 is low complexity, 5-7 indicates moderate complexity, 8-10 is high complexity, and 11+ is very high complexity.
See also Experiments correlating code metrics to bug density from P.SE which goes deeper into the actual measures.
1
The C language allows for up to 127 levels of nested blocks; like 640KB of RAM, that’s all anyone should ever need.
In practice, if you find yourself nesting more than 4 or 5 levels deep, think about factoring some of those inner levels out to their own functions (or re-think your algorithm). If nothing else, the code will be easier to scan.
1
I strongly recommend you to read “Clean Code” by Robert Martin, an extract of which says about nested structures:
Blocks and Indenting
…the blocks within
if
statements,else
statements,while
statements, and so on should be one line long. Probably that line
should be a function call. Not only does this keep the enclosing
function small, but it also adds documentary value because the
function called within the block can have a nicely descriptive name.This also implies that functions should not be large enough to hold
nested structures. Therefore, the indent level of a function
should not be greater than one or two. This, of course, makes the
functions easier to read and understand.
So Bob Martin’s recommendation is that the dept of nested structured should be two at most.
I agree with that and, although I don’t always comply with it, at least I try.
Also, according with static analisys tool PDM’s default configuration, the cyclomatic complexity of a function should not exceed 11, which is easily reached if you go beyond a dept of two.
1
As with most questions about coding standards, the answer is: Whatever makes your code more readable.
I would argue that’s usually fairly close to zero embedded layers of logic. But sometimes it isn’t, and sticking vehemently to rules against common sense is more damaging than keeping to the simple policy of reading your own code, or getting someone else to.
Anything that makes it more readable, do it.
I personally try to avoid more than four or five levels deep in a single function. More than that would be a bad “code smell”. I would suggest try to avoid that by adjusting the structure of the program or re-formulating your problem.
1
One downside to nested loops not mentioned yet: If each loop iterates over a large dataset, your algorithm will have high complexity classes. For example,
foreach(foo in foos) {
foreach(bar in bars) {
foreach(baz in bazzes) {
foreach(buzz in buzzes) {
do_a_thing(foo, bar, baz, buzz);
}
}
}
}
Will run in roughly O(n^4)
time if foos
, bars
, bazzes
and buzzes
are all about the same size.
This isn’t an issue if the collections are always going to be small. Then, everyone else’s advice applies. If your collections have a decent chance of being 1000’s of items large or larger, though, it would be worth looking for a faster algorithm if possible.