Return Modified Value

Removes smells
Compare
Symptom
Human

A function that mutates one of its parameters in place and returns nothing — `addTax(order)` modifies `order.total` directly.

Agent

A function that mutates one of its parameters in place; the agent reading the signature can't tell which parameters get mutated without reading the body.

Goal
Human

Instead of mutating a parameter in place, the function returns the modified value so the caller reassigns.

Agent

The function returns the modified value; the agent reads the signature and knows the function is a transformation, not a mutator.

Before the refactoring

function addTax(order) {
order.total *= 1.1;
}
addTax(order);

After the refactoring

function withTax(order) {
return { ...order, total: order.total * 1.1 };
}
order = withTax(order);
Example source: Illustrative example written for this site, not a quotation from any source.
Pressure
Human

Callers can't tell from the signature that a parameter is being mutated; snapshotting and equality become unreliable; functional composition is blocked.

Agent

The agent reasoning about any call must check the function body to identify which parameters mutate; equality, snapshotting, and composition all become guarded.

Tradeoff
Human

Callers must remember to capture the returned value; if any forget, they keep the unmodified original. Mark the parameter readonly so the type system helps.

Agent

Callers must remember to capture the returned value; if any forget they keep the unmodified original, which the agent verifying must check at every call site (or rely on a readonly parameter type).

Relief
Human

Side effects on inputs disappear; the function reads as a transformation; equality and snapshotting become possible.

Agent

Side effects on inputs disappear from the agent's contract reasoning; the function reads as a pure transformation; composition and snapshotting work.

Trap
Human

Refactoring every parameter-mutator to return-modified-value, including ones where the in-place mutation is genuinely the contract callers want — a performance-sensitive batch operation, for example.

Agent

Forcing return-modified-value on every in-place mutator — including ones where mutation is the contract callers want (performance-critical batch ops) — substitutes one mismatch for another.