Replace Function with Command

Removes smells
Compare
Symptom
Human

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.

Agent

A function whose body holds many shared locals across conceptually distinct sub-steps; the agent extracting any step must thread temps through helper parameters.

Goal
Human

A function with rich internal state becomes an object whose methods can share that state — easier to extract, name, and test in pieces.

Agent

Each sub-step becomes a named method on the command object; sub-step methods share state through fields the agent reads from one class file, and tests target one method at a time without simulating the full function body.

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();
Example source: Illustrative example written for this site, not a quotation from any source.
Pressure
Human

Extracting sub-steps means threading every shared temp through helper parameters; reasoning about any single step requires holding the whole state in working memory.

Agent

Every step the agent wants to extract drags shared state through parameter lists; the function's algorithm shape resists decomposition.

Tradeoff
Human

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.

Agent

Command ceremony (constructor + execute + named private methods) is overhead for functions without genuine multi-step state; the agent now navigates a class where one function used to suffice.

Relief
Human

Long sequences become labeled steps; tests target each step on the command; subclasses or strategies can vary parts of the algorithm.

Agent

Each sub-step becomes a named method on the command; the agent extracts and tests them in pieces without rewiring shared state.

Trap
Human

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.

Agent

Promoting every long function to a command — including ones with no genuine shared state — adds class ceremony the agent must navigate without gaining any decomposition advantage.