Back to all posts

Stop Nesting So Deep

André Schärpf

You open a method. Forty lines in, you're five levels deep. IF inside LOOP AT inside IF inside LOOP AT inside IF. You scroll sideways to read the actual logic. You have no idea what condition got you here. Welcome to most ABAP codebases.

Deeply nested code is one of the most common readability problems in ABAP, and one of the least talked about. People will argue for hours about naming conventions or where to put line breaks in a SELECT statement, but nobody bats an eye at a method that reads like a topographic map.

Nesting is cognitive load

Each level of nesting is another condition the reader has to hold in their head. "We're inside this loop, but only if this flag is set, and only for items where status equals 3, and only when the document type is..." By level three, most people start losing track. By level five, the code is effectively write-only. The author understood it when they wrote it. Nobody else will, including the author six months later.

ABAP makes it worse

Most languages have this problem. ABAP makes it worse — not because of the nesting keywords themselves (IF, LOOP AT, CASE are compact enough), but because everything you write inside them is not. Table reads, structure assignments, method calls with named parameters — ABAP statements run long. Horizontal space is already scarce, and every nesting level steals more of it. By level four, you're writing your actual logic in a narrow column on the right side of the screen.

Other languages at least have compact syntax. A Python for with a ternary fits on one line. ABAP does not give you that option. So the penalty for nesting is higher, and the incentive to avoid it should be too.

The fixes

None of this is new. The techniques to flatten nested code have been around for decades. The problem is not awareness, it's application.

Early returns and guard clauses. Instead of wrapping an entire method body in IF lv_valid = abap_true, check the negative case first and RETURN. Flip the condition, exit early, and keep the happy path at the top level. One IF eliminated, one nesting level gone.

" Instead of this:
METHOD do_something.
  IF lv_valid = abap_true.
    " 80 lines of logic
  ENDIF.
ENDMETHOD.

" Do this:
METHOD do_something.
  IF lv_valid <> abap_true.
    RETURN.
  ENDIF.
  " 80 lines of logic, no nesting
ENDMETHOD.

Extract methods. If a LOOP AT body is 40 lines with nested IF statements, that body is a method. Pull it out. Give it a name that describes what it does. The loop becomes two lines, the extracted method becomes testable on its own, and both are easier to read.

Replace nested IF chains with CASE. If you find yourself writing IF ... ELSEIF ... ELSEIF ... ELSEIF, that's a CASE statement. Or better yet, a lookup table. Table-driven logic scales better than branching and is easier to extend without touching control flow.

Use modern ABAP syntax. VALUE, REDUCE, FILTER, and inline declarations (available from 7.40+) reduce the need for temporary variables and intermediate loops. A LOOP AT that builds a result table can often become a single VALUE expression. Fewer intermediate steps, fewer places to nest.

The real problem

Most developers know about early returns. They know about extracting methods. They just don't do it consistently, because the code works and refactoring feels optional. There's always another ticket, another deadline, another reason to leave the 200-line method alone.

But code is read far more often than it's written. An 800-line method with six nesting levels works fine for the machine. It does not work for the next developer who has to fix a bug in it at 4 PM on a Friday. That developer will read the first 50 lines, lose context, start the debugger, step through 300 iterations of a loop, and eventually find the one IF branch that matters. That's an hour of work that should have been five minutes.

Writing flat code is not about aesthetics. It's about respect for the next reader's time.

A rule of thumb

If you're deeper than two levels of nesting, reconsider. If you're deeper than three, refactor. This is not a rigid law. Some algorithms genuinely need three levels. But treat depth as a smell. The deeper the nesting, the higher the chance the method is doing too much and should be split up.

The best code doesn't make you think about its structure at all. You read it top to bottom, each step follows from the last, and you never have to count indentation levels to figure out where you are. That's worth the effort of flattening.