Replace Error Code with Exception

Removes smells
Symptom

Functions returning numeric or string codes for failure — `withdraw(amount)` returning -1 for insufficient funds — relying on callers to check and propagate.

Goal

Numeric or string error codes that callers must remember to check are replaced with exceptions that propagate by default.

Before the refactoring

function withdraw(amount) {
if (amount > balance) return -1;
balance -= amount;
return 0;
}

After the refactoring

function withdraw(amount) {
if (amount > balance) throw new InsufficientFunds();
balance -= amount;
}
Example source: Illustrative example written for this site, not a quotation from any source.
Pressure

Forgetting to check silently swallows the error; the type system can't enforce the check; cleanup logic scatters across consumers.

Tradeoff

Exceptions for predictable conditions misuse the mechanism — only convert codes that represent genuine, exceptional, unrecoverable failures.

Relief

Forgetting to check no longer silently swallows the error; the type system marks the failure path; cleanup happens via finally / try-with.

Trap

Using exceptions for predictable conditions — turning every error code into an exception introduces control flow via throws that callers must catch.