Symptom

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 of the function rises with every branching point the procedure has accumulated.

Goal

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 is encoded structurally in the function's name and signature rather than buried in its 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);
}
Example source: Illustrative example written for this site; the smell itself is catalogued in Martin Fowler's Refactoring (Addison-Wesley, 2018), see the chapter on Bad Smells in Code.
Pressure

Each line is an opportunity for the reader to lose context; understanding the whole function at once raises 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.

Tradeoff

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 drops only when the names earn their keep.

Relief

Faster to read, easier to test, simpler to change one step without touching the others. The team's 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.

Trap

A fan-out of one-line helpers where the workflow can no longer be read linearly — extraction without earning a name introduces 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 .