Functions whose body has dozens of lines and a mix of concerns — fetching, calculating, formatting, and logging all interwoven. The reader must hold all of them simultaneously while tracing the path through the body, and the cyclomatic complexity of the function rises with every branching point the procedure has accumulated.
The function's body has more tokens than the agent can hold in one reasoning step; verifying behavior preservation means re-reading the entire body on every edit. Long bodies push the agent into chained reasoning passes where each pass re-establishes the parts of the procedure relevant to the current edit, paying full context-window load every time.
Each function reads as a sequence of named single-responsibility steps; nothing does more than its name advertises. The reader's mental model of each step fits in working memory simultaneously with the others, and separation of concerns is encoded structurally in the function's name and signature rather than buried in its body.
Each function is a verifiable unit small enough that the agent can reason about its full behavior in a single reasoning step. The procedure decomposes into a sequence of named contracts the agent can verify independently; behavior preservation across edits scales with the number of touched contracts, not with the size of the original body.
Smellier version
function ship(order) {if (!order.id) throw new Error('missing id');const tax = order.total * 0.1;const grand = order.total + tax;email(order.user, `Total ${grand}`);log(order);}
Fresher version
function ship(order) {validate(order);const grand = withTax(order);notify(order, grand);}
Each line is an opportunity for the reader to lose context; understanding the whole function at once raises cognitive load with every added line. Bugs sneak in where one concern's state collides with another's — and reviewers ship the merge because the function's signature gave them no way to see which lines belonged to which concern.
Every edit pays the full context-window load of re-reading the body; chained edits raise the chance of missing a cross-statement invariant. The agent's completeness-check cost multiplies across statements the edit didn't touch — an edit that satisfies the part of the function it focused on while breaking an adjacent invariant ships as a partial fix that passes the targeted test.
Splitting introduces a navigation cost — readers gain named outlines but pay function-jump hops to follow the implementation. The wrong granularity buys clutter without comprehension; the right granularity makes the workflow visible at signature level while leaving the per-step logic inside each helper. The team's verification cost drops only when the names earn their keep.
Splitting inflates context-window load — the agent now loads N function definitions to follow what was once one body. Worth it when the outline is clearer than the linear body; not worth it when the helpers fragment the procedure into pieces that demand more reasoning-step cost to assemble than the original body did to read.
Faster to read, easier to test, simpler to change one step without touching the others. The team's debugging cost drops because the failing concern is named at the call site; each helper's contract is independently testable, so a regression in one step doesn't require re-verifying the whole procedure.
Each extracted function fits inside one read; the agent verifies behavior against one signature, dropping context-window load per edit. The verification-surface cost of any change contracts to the touched function plus its callers, and cross-function invariants surface as signature mismatches the type checker catches in one static read.
A fan-out of one-line helpers where the workflow can no longer be read linearly — extraction without earning a name introduces accidental complexity by fragmenting the procedure into pieces too small to mean anything. The reader pays the function-jump cost on every line while gaining nothing in comprehension cost.
Forces the agent to chase a dozen function definitions for what was once a 20-line procedure — context-window load inflates and cross-function invariants disappear. The agent pays full retrieval cost on every per-step navigation; the splitting that was meant to drop reasoning-step cost instead spreads it across more files.