Change Reference to Value

Removes smells
Symptom

A class treated as a sharable record (with public mutable fields or setters) used by many consumers — mutating it in one place affects every reader.

Goal

An object treated as a sharable record (with setters) becomes a value object — immutable, equal by content, replaced rather than mutated.

Before the refactoring

class Phone {
constructor() { this.area = null; this.number = null; }
}
phone.area = '617';

After the refactoring

class Phone {
constructor(area, number) { this._area = area; this._number = number; }
area() { return this._area; }
number() { return this._number; }
withArea(area) { return new Phone(area, this._number); }
}
Example source: Illustrative example written for this site, not a quotation from any source.
Pressure

Concurrent reasoning becomes hazardous; the type system can't enforce immutability; consumers can't trust the object's state between operations.

Tradeoff

Comparison semantics shift from identity to equality — every call site that depended on `===` or identity caches needs review.

Relief

Concurrency hazards disappear; the type system can mark fields readonly; the object can travel safely across boundaries.

Trap

Switching to value semantics for objects that genuinely belong as references — domain entities with identity (Customer, Account) — strips the identity that consumers depend on.