Code in Motion > The Perils of Indentation

32.3. The Perils of Indentation

We've all been taught to use indentation to show the depth of nesting in logical blocks of code. The deeper the nesting, the farther to the right of the page the nested code appears. Formatting code this way is a good idea, but not because it makes the code any easier to read.

If anything, deeply indented code is harder to read. Important logic is crowded off to the right, submerged to almost footnote-like insignificance by the layers of if-then-else code that surrounds it, while trivial tests applied in outer blocks seem elevated in importance. So, while indentation is useful for showing where blocks begin and end, it doesn't make the code any easier for us to comprehend.

The greater peril is not the indentation, however: it's the nesting. Nested code strains human comprehension, plain and simple. Edward Tufte was not being complimentary when he wrote that "Sometimes [PowerPoint] bullet hierarchies are so complex and intensely nested that they resemble computer code." In Code Complete (see "Further Reading," at the end of this chapter), Steve McConnell warns against using nested if statements—not because they're inefficient or ineffective, but because they're hard on human comprehension. "To understand the code, you have to keep the whole set of nested ifs in your mind at once," he says. It's no surprise that research points to nested conditionals as the most bug-prone of all programming constructs. We have a bit of anecdotal evidence for this, as you'll read in the section "DiffMerge's Checkered Past."

So the value of indenting each nesting level is not in making code more comprehensible, but in making the coder more aware of incomprehensibility. "Seven Pillars" advises coders to "overcome indentation"—that is, to code without deep nesting. "This is the most difficult of these practices," admits Seiwald, "as it requires the most artifice and can often influence the implementation of individual functions."

Steve McConnell demonstrates some useful implementations in the "Taming Dangerously Deep Nesting" section of Code Complete. DiffMerge makes heavy use of two of them: case statements and decision tables. The end result, as you can see in the DiffMerge source, is that the code itself takes on an outline form that lets us discern the big-picture logic by scanning down the left side of the page. Our brains, conditioned to reading outlines in natural-language text, find this easier to comprehend than the sideways-V form of deeply nested code.