What steps and measures can I take to prevent deep indentations in my code?
-
2A lot of people will talk about refactoring here. Maybe this is too much to ask, but if you posted some (not too long) code that is deeply indented, and people could show you how they'd refactor it. Of course, that probably makes the question language specific then... – Paddyslacker Sep 09 '10 at 21:34
-
3Use a smaller tab width. – mipadi Sep 21 '10 at 17:47
-
6**Arrowhead** anti-pattern. Google it, loads of tips – NimChimpsky Sep 22 '10 at 10:43
-
2Stop using python :D – back2dos Oct 08 '10 at 14:18
-
It's time to look at your control and loop logic. Likely your code is more complicated than it needs to be, and a re-conceptualization of the problem will lead to much shorter code. Study good code and learn the techniques. – Macneil Aug 15 '11 at 02:56
9 Answers
The best thing you can do is extract methods:
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);
}
// ....
}

- 6,305
- 2
- 33
- 33
-
3This also works for complex `if`-conditions. Taken to the extreme, you'll end up with executable pseudocode. – Alan Plum Sep 21 '10 at 16:17
-
Other best thing we can do is to probably drop unnecessary `else` blocks. – sepehr Mar 22 '18 at 09:19
Maybe you could consider guard clauses?
instead of
public void DoSomething(int value){
if (someCondition){
if(someOtherCondition){
if(yetAnotherCondition){
//Finally execute some code
}
}
}
}
Do
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
}
If you ever get a chance I'd reccommend you read Code Complete by Steve McConnell. He's got a lot of great advise on these topics.
http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=pd_sim_b_6
For more about "guard clauses" see: https://sourcemaking.com/refactoring/replace-nested-conditional-with-guard-clauses

- 180
- 1
- 15

- 271
- 2
- 4
Deep indentation is usually not a problem if every function/method in your program does one and only one thing. Occasionally, it might be necessary to nest conditionals a few levels deep, but I can honestly say I've only written deeply indented code a handful of times in 12+ years of coding.

- 6,173
- 2
- 39
- 51
Invert your if
s.
Instead of:
if (foo != null)
{
something;
something;
if (x)
{
something;
}
something;
}
else
{
boohoo;
}
I'd write:
if (foo == null)
{
boohoo;
return;
}
something;
something;
if (x)
{
something;
}
something;
The same applies to if
-else
blocks. If else
is shorter / less nested, then revert them.
Check parameters' values in one place
Check all the parameters for illegal values as soon as you enter your method, then proceed knowing that you're safe. It makes for more readable code, but it also saves you piling up conditional blocks later on and spreading these checks all over the subroutine.

- 9,721
- 4
- 37
- 58
-
1
-
@ThomasLauria not that I'd know of. It's just exiting early. `If`s at the beginning of code which stop the execution flow due to some condition not being met are also known as *safeguard clauses*, like @JasonTuran pointed out. And that seems to be as close as it gets to having a distinct name. – Konrad Morawski Aug 11 '16 at 12:25
-
some years ago my supervisor told me that this style was named as "linear programming", but I think this was a phantasm of him ;) – Thomas Lauria Aug 12 '16 at 16:54
Typically, I have seen that deeply indented code is usually problematic code. If you are facing this problem, then step back and evaluate if your function is doing too many things.
At the same time, to answer your question, if there is a need for indentation that deep, I would suggest that you let it be there. For the simple reason that in such code, the indentation will help since it is likely to be a very long piece of code.

- 331
- 2
- 7
Break nested components (especially repeated ones) out into separate functions (this is easier if your language supports closures) or replace a series of nested loops with a recursion.
Also, indent two spaces instead of four.

- 1,635
- 10
- 12
-
6Once you've gone to the step of changing your tab width, you're in deep trouble... – Daenyth Sep 21 '10 at 20:33
-
-
7
I didn't believe it myself, but according to Code Complete this is an appropriate place to use break
(if your team is on board). I'd imagine this is more acceptable with C++ programmers though, where break
used in switch
statements than it is with Delphi programmers where break
is only used when you don't feel like writing a while
loop.

- 6,897
- 1
- 33
- 57
I don't see deep indentations as a categorical problem to be removed (nor do I see refactoring as the true answer for everything).
Typically instead of nested ifs, I like to write logical statements:
if (foo && bar && baz)
rather than
if foo
if bar
if baz

- 8,560
- 1
- 33
- 41
-
The problem is, there do also exist for and while loops that don't fall under this rule. – Tamara Wijsman Sep 22 '10 at 18:00
-
@TomWij: I am not trying to induce a categorical imperative about style. – Paul Nathan Sep 22 '10 at 18:07
-
2
Indentation is really a think to fight, indeed. What I learned to do is to divide the method into pieces first, then use a weird trick to skip every following pieces if one piece failed. Here is an example :
Instead of :
{if (networkCardIsOn() == true)
{if (PingToServer() == true)
{if (AccesLogin(login,pass) == true)
{if (nextCondition == true)
...
}
}
}
I currently write :
{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();
}
}
...
This has seem strange to me at a first, but since I use this, the maintenance cost has been divided by half, and my brain is cooler at the end of the day.
In fact, the gain introduced by this "technique" is that the code complexity is really divided because the code is less dense.
While reading the code, you don't have to remember anything about the past conditions : if your are at that point X in the code, the previous steps are passed and have succeeded.
Another gain is that "escape path and condition" from all those nested "if-else" is simplified.

- 1,421
- 1
- 14
- 20
-
Can you elaborate on "the maintenance cost has been divided by half" Also, how would you really know which if halted execution ? – Chris Sep 22 '10 at 10:19
-
-
2If you want to go even simply, you have a goto error_handling line. – Paul Nathan Sep 22 '10 at 17:26
-
-
@Murph. It's not about to be nice. It's about to be simple, dead easy to maintain. I know that 'look' strange, but it isn't. It's a way the split the complexity by making small individual steps. – Rabskatran Oct 08 '10 at 15:15
-
Yes but that's my point I don't think you've made it less complex. But I'm weird. – Murph Oct 08 '10 at 15:52
-
4
-
I don't like this code. It looks overbloated with low-level conditional checks. – rds Aug 16 '11 at 11:35
-
@Newtopian: One reason is because exception-handling constructs can *implicitly* create many possible control flows, most of which are near-invisible to the casual eye. This invites hard-to-find and hard-to-test bugs. (For example, it's famously difficult to write exception-safe C++.) Explicit control flow simultaneously limits, and makes clearly visible, the set of possible control flows. – j_random_hacker Jul 27 '15 at 20:52