Engineering Craft › Clean Code & Principles
Deep Nesting
Too many levels of ifs and loops; flatten them with guard clauses.
Also known as: deep nesting, arrow code, nested ifs
Deep nesting means too many levels of ifs and loops inside one another. Code drifts to the right, and you have to hold several conditions in your head to know when a line runs.
def ship(order):
if order is not None:
if order.is_paid:
if order.items:
for item in order.items:
if item.in_stock:
send(item)
Five levels deep. Which condition does the last line depend on?
Flatten it
Use guard clauses: handle the bad cases first, and return.
def ship(order):
if order is None or not order.is_paid or not order.items:
return
for item in order.items:
if item.in_stock:
send(item)
Extract a function for the inner part (extract function):
def ship(order):
if not can_ship(order):
return
for item in in_stock_items(order):
send(item)
Use continue inside loops to skip cases early:
for item in order.items:
if not item.in_stock:
continue
send(item)
A rough guide
Two or three levels are normal. More than three is a signal to refactor. Deeply nested code also tends to have high cyclomatic complexity, many paths to test.
Other causes
- Handling errors with nested
tryblocks, or a pyramid of callbacks (callback hell). - A function doing too much (long method).
Linters can warn when nesting passes a limit. See readability.