Stop building utility layers that hide decisions
Abstraction without opinion delays the decisions that make software correct.
Judgment: Utilities should encode a decision, not avoid one.
A utility layer that avoids decisions does not reduce complexity. It relocates it. The complexity returns later, when the system needs a judgment and the utility has none.
Mechanism
Utilities are a way to enforce a policy. If they are only a collection of helpers, they are not a layer, they are just a junk drawer. The real mechanism is constraint: the utility chooses one path and makes other paths harder.
export function toMoney(value, currency = 'USD') {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency,
}).format(value)
}
This is a decision. It defines locale and format. It is not pretending to be universal.
Tradeoffs
Opinionated utilities can be wrong. That is fine. The cost of a wrong opinion is lower than the cost of no opinion. You can change a decision. You cannot debug a vacuum.
Signal
If your utility API reads like a wrapper around every possible option, you have not built a layer. You have built an escape hatch.