AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Never Nesting

skill-morzecrew-agent-skills-never-nesting · by morzecrew

Flatten deeply nested code using guard clauses, early return/continue, function extraction, and error-handling redesign - and recognize when nesting should stay (symmetric branches, RAII/defer cleanup idioms). Use when writing or refactoring code with deep indentation, pyramid-of-doom or arrow-shaped if/else, nested loops or try/catch blocks, a buried happy path, or when the user mentions nesting…

No reviews yet
0 installs
13 views
0.0% view→install

Install

$ agentstack add skill-morzecrew-agent-skills-never-nesting

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-morzecrew-agent-skills-never-nesting)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
18d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Never Nesting? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Never Nesting

Each level of indentation is one more condition the reader must hold as true to understand the innermost line. SonarSource's cognitive-complexity metric formalizes this: every control structure costs +1, plus +1 for each level of nesting it sits under. Four sequential guard clauses cost 4; the same logic as four nested ifs costs 1+2+3+4 = 10. Nesting doesn't add difficulty linearly — it compounds. The Linux kernel style guide puts it bluntly: "if you need more than 3 levels of indentation, you're screwed anyway, and should fix your program."

Treat three levels as a soft ceiling and a fourth as a refactoring signal, not a formatting problem. The moves below flatten code; the last section covers the cases where flattening makes code worse.

Use this skill when

  • Writing a function that is growing nested if/for/try blocks.
  • Refactoring arrow code / pyramid-of-doom conditionals (if { if { if { ... }}}).
  • The happy path sits several indents deep with error handling wrapped around it.
  • Reviewing code for readability or a complexity-metric violation.
  • The user mentions nesting, guard clauses, early returns, or flattening conditionals.

Do not use this skill when

  • The user explicitly wants the existing structure preserved.
  • Both branches of a conditional are equally normal behavior (see "When not to flatten").
  • Manual resource cleanup makes early returns leak (see "When not to flatten").

The move-set

| Move | Use when | Effect | | --- | --- | --- | | Guard clause (invert + early return) | edge/error cases wrap the happy path | happy path drops to base indent | | continue / break | per-item conditions nest a loop body | loop body flattens | | Extract function | a nested block is a coherent, nameable unit | resets nesting to zero; names intent | | Define errors out of existence | every caller must check or catch | the error branch disappears entirely | | Aggregate error handling | try/catch wraps each individual call | one handler at one level | | Dispatch table / pattern match | nested if/else selects among cases | branching becomes data |

Guard clauses: invert, fail fast, return early

Fowler's "Replace Nested Conditional with Guard Clauses": handle each unusual case first with an immediate return/raise, so the remaining code needs no else and the real work sits at base indentation. The guards read as a declaration of the function's preconditions.

# Before: reader holds 3 conditions to understand the core 3 lines
def save(user, payload):
    if user is not None:
        if user.is_active:
            if payload.is_valid():
                record = build_record(payload)
                store(record)
                return record
            else:
                raise InvalidPayload()
        else:
            raise InactiveUser()
    else:
        raise MissingUser()

# After: each condition is discharged, then forgotten
def save(user, payload):
    if user is None:
        raise MissingUser()
    if not user.is_active:
        raise InactiveUser()
    if not payload.is_valid():
        raise InvalidPayload()

    record = build_record(payload)
    store(record)
    return record

Mechanics: (1) negate the outermost condition and exit early in that branch; (2) the else is now dead — delete it and promote its body one level; (3) repeat inward until the happy path is flat. Inside loops, the same inversion uses continue (or break) instead of return:

for item in items:
    if item.skip:
        continue
    process(item)

If several guards share the same failure response, one combined condition (if not (a and b and c): raise ...) can beat three separate guards — choose whichever states the requirement most directly.

Extraction: name the block, reset the depth

When a nested block does one coherent thing, pull it into a function. This removes indentation at the call site, gives the block a name that documents intent, and — because complexity metrics assess each function separately — resets the nesting count to zero inside the new function.

# Before: the interesting logic starts 4 levels deep
def process_downloads(downloads):
    for d in downloads:
        if d.state == "in_progress":
            result = d.process()
            if result.is_error():
                if result.retriable and d.retries < 3:
                    d.retries += 1
                    d.state = "pending"
                else:
                    fail(d)

# After: the loop is a summary; the extracted function is guard-flat
def process_downloads(downloads):
    for d in downloads:
        if d.state == "in_progress":
            handle_result(d, d.process())

def handle_result(d, result):
    if not result.is_error():
        return
    if result.retriable and d.retries < 3:
        d.retries += 1
        d.state = "pending"
        return
    fail(d)

For a long function with distinct phases, extract each phase so the top level reads as an outline. Real refactors alternate the moves: extract to drop a level, then invert inside the extraction.

Flatten error handling at the source

Nesting is often not a control-flow problem but an API-design problem. Two moves from Ousterhout's A Philosophy of Software Design:

  • Define errors out of existence. Redesign the operation so the "error"

case is normal behavior and the branch vanishes for every caller. Deleting a missing key throws → make deletion idempotent (succeed if already absent). Out-of-range substring throws (Java) → clamp to the valid range (Python slicing). One API change deletes a try/except from every call site.

  • Aggregate exception handling. Instead of wrapping each call in its own

try/catch (pyramids of handlers), let exceptions propagate to a single handler at the level that can actually respond — a request-level error handler, a per-item try around the loop body, a top-level retry loop.

Replace conditional trees with data or idioms

  • A nested if/else chain that maps a value to behavior is a **dispatch

table**: handlers[kind](payload) — branching becomes a data lookup.

  • Prefer built-in flat forms where the language has them: pattern matching

(match/switch with cases), comprehensions and filter/map for filter-inside-loop, with/using for acquire-release nesting.

When not to flatten

  • Symmetric branches. A guard clause signals "this branch is not what the

function is about." Fowler's rule: use guards when one branch is the unusual case; when both branches are normal behavior (days = 366 if leap else 365, buy vs sell), keep if/else (or a conditional expression) so both get equal emphasis — a guard would falsely mark one as an error path.

  • Manual cleanup languages. Early return is safe only when cleanup runs

automatically: RAII destructors (C++/Rust), defer (Go), context managers (with), try/finally, using (C#). In C-style code with manual free/unlock, extra returns leak resources; the flat idiom there is a single goto err cleanup chain (the Linux kernel's own pattern) — don't graft early returns onto it.

  • Trivial one-off extraction. Don't extract a two-line block used once if

the name adds nothing; a guard clause alone is often enough. Each extraction also adds a definition the reader may have to chase.

  • Single-exit codebases. If the style guide bans early returns, flatten by

extraction and dispatch tables instead of inversion.

The goal is fewer conditions held in the reader's head, not a zero-indent contest.

Quick checklist

  • Any function past ~3 levels? It's a candidate.
  • Can edge cases become guards so the happy path reaches base indent?
  • Is a nested block a nameable unit? Extract it.
  • Is the nesting caused by an API that throws where it could tolerate? Fix the API.
  • Is any branch you're about to guard actually normal behavior? Keep if/else.
  • Does an early return skip manual cleanup? Use the language's cleanup idiom first.

Related skills

  • naming-things — extraction only pays off if the new function's name informs; naming difficulty means the block isn't a coherent unit yet.
  • self-documenting-code — guard clauses and extracted functions document intent that comments would otherwise carry.
  • less-code-same-behavior — flattening often reveals duplicate branches that can be merged or deleted.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.