concept

Abstraction

Exposing what a component does while hiding how it does it, so callers depend on the contract rather than the mechanism.

designinterfacescomplexity

A good abstraction lets you reason about a system without opening it. save(order) tells you what happens; whether it writes to Postgres, an outbox or a queue is not your problem.

The cost is that every abstraction is a bet that the hidden detail will not matter. When the bet is wrong the abstraction leaks — the caller starts having to know about connection timeouts, transaction boundaries or eventual consistency anyway, and now it has to know about them through an interface that was designed to hide them. That is worse than no abstraction at all.

Practical guidance: abstract over things that genuinely vary (a payment provider, a message broker), and resist abstracting over things that do not. A DatabaseInterface with one implementation is speculative generality; it costs indirection today for optionality you may never exercise.