A long function with many local variables and conceptually distinct sub-steps that all share state — the function body reads as a multi-stage algorithm coordinating temps.
A function with rich internal state becomes an object whose methods can share that state — easier to extract, name, and test in pieces.
Before the refactoring
function score(candidate) {let total = candidate.experience * 10;if (candidate.hasCertifications) total += 25;total -= candidate.gaps * 5;total += candidate.referrals * 8;return total;}
After the refactoring
class Scorer {constructor(candidate) { this.candidate = candidate; }execute() {return this.base() + this.bonus() - this.penalty();}base() { return this.candidate.experience * 10 + (this.candidate.hasCertifications ? 25 : 0); }bonus() { return this.candidate.referrals * 8; }penalty() { return this.candidate.gaps * 5; }}new Scorer(candidate).execute();
Extracting sub-steps means threading every shared temp through helper parameters; reasoning about any single step requires holding the whole state in working memory.
Promoting a function to a command adds ceremony (constructor, method calls). Only worth it when the function genuinely needs its own intermediate state or multiple entry points.
Long sequences become labeled steps; tests target each step on the command; subclasses or strategies can vary parts of the algorithm.
Promoting a simple function (no shared state, no multiple entry points) to a command — adds constructor + execute() ceremony around a body that worked as a plain function.