Concept · SOLID principles
Open–closed principle
Make code open for extension but closed for modification: add new behaviour by adding code, at the points where variation is real.
The open–closed principle (OCP), the O in SOLID, was stated by Bertrand Meyer in 1988: software entities should be open for extension but closed for modification. In practice: when a new case arrives, you should be able to support it by adding new code rather than editing existing, tested code.
The smell it targets
A switch on a kind, repeated across the codebase:
switch payment.Method {
case "card": // ...
case "wallet": // ...
case "bank": // ...
}If the same switch appears in validation, fee calculation and refunds, every new payment method means editing all three — and missing one is a bug.
The usual fix
Make the varying behaviour an interface, and each case a type that implements it:
type PaymentMethod interface {
Validate(p Payment) error
Fee(amount Money) Money
Refund(ctx context.Context, p Payment) error
}Adding QRIS is now a new type plus one registration line; existing methods are untouched. In Go and TypeScript, a function value often suffices when only one operation varies — the strategy pattern. Other extension mechanisms include middleware chains, event subscribers and configuration-driven tables.
Apply it where variation is real
Every extension point is indirection a reader must follow. Martin's own advice is to protect against the kinds of change you have evidence for — usually after the second or third time that kind of change happens. A switch over two cases that hasn't changed in years is simpler than an interface, factory and registry. Write the simple version, and refactor towards OCP when real variation appears (YAGNI).
OCP is closely tied to the other SOLID principles: Liskov substitution makes extensions safe, and dependency inversion lets core code depend on the interface rather than every implementation. See the SOLID lesson.