Design Patterns
Each pattern as a response to an observed problem, with its trade-off and its simpler alternative — because a pattern applied without the problem is just indirection.
Their durable value is a shared name for a shape you already built. Treated as a construction kit instead of a naming scheme, they add structure nobody needed.
Behaviour that varies by a recurring kind, held in a value instead of a conditional. Worth it when the variation is real and stable — and a map of functions usually gets you there first.
Encapsulates a construction decision that callers should not make. When there is no decision, a factory is a function that calls `new` and charges you a file for it.
Your interface on one side, someone else's on the other, and a translation in between. The most consistently useful pattern here, because it is an anti-corruption layer in miniature.
A small interface over a subsystem whose full surface most callers do not need. Useful when the subsystem is genuinely complex and dangerous when the facade becomes the only way in.
Add behaviour by wrapping rather than by editing. Excellent for logging, caching and retry; the cost is a stack trace nobody can read and behaviour that depends on wrapping order.
The producer stops knowing its consumers. That is the point and the price: nothing in the code shows what happens when the event fires.
An action turned into a value. Pointless if you only intend to call it — and genuinely load-bearing the moment you need to queue, retry, audit, schedule or undo it.
Behaviour that varies by lifecycle state, held in a type per state. Often the right instinct — and an explicit state machine is usually the clearer way to satisfy it.
A base class fixes the steps and subclasses fill in two of them. It works, and passing the two steps in as functions does the same job without a hierarchy.
The anti-lesson. Abstractions with one implementation, event buses for local calls, factories of factories — structure added for problems nobody has, and it is not free.