A function body that needs a mental outline before it can be read — multiple concerns interleaved, or chunks of statements that share a single domain purpose without a name. The reader's comprehension cost rises because every read reconstructs the outline; small edits to one concern require holding all the others in working memory.
Each function reads as a single named domain step — what it does, not how. The calling code becomes a sequence of named intentions; readers verify the workflow at the top level and drill into helpers only when the named step's body is the point of interest, supporting separation of concerns at the procedural level.
Before the refactoring
function invoiceTotal(invoice) {let total = 0;for (const line of invoice.lines) {total += line.qty * line.unitPrice;if (line.qty >= 100) total -= line.qty * line.unitPrice * 0.05;}total += total * invoice.taxRate;return Math.round(total * 100) / 100;}
After the refactoring
function invoiceTotal(invoice) {const subtotal = subtotalAfterBulkDiscount(invoice);const withTax = subtotal * (1 + invoice.taxRate);return roundToCents(withTax);}
Every reader pays the outline cost on every read; small edits to one concern require holding all the others in working memory, and PRs touch the same function for unrelated reasons. The team's verification cost compounds across reviewers who must re-derive the function's structure each time; merge conflicts collect at the same body.
Over-eager extraction can produce a fan-out of one-line functions; aim for extractions that earn their name with at least one decision or transformation. The team's maintenance cost can rise rather than drop if the extractions don't carry domain meaning, because every helper becomes a name to find, load, and verify on every traversal.
Calling code becomes a sequence of named intentions; bugs concentrate inside the now-named subroutines because the reader can localize the failure to one named step. The team's enhancement cost drops because adding a new step is one new function rather than a new branch inside an already-cluttered body, and tests target the helper directly.
Tiny one-line helpers where the workflow can no longer be read linearly — extraction that doesn't earn its name fragments the procedure into pieces too small to mean anything. The fan-out adds accidental complexity to the call graph; readers carry the cognitive load of jumping between trivial helpers to reconstruct the original procedure.