# 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.

Concept · SOLID principles · https://levelcode.org/concepts/open-closed

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:

```go
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:

```go
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](https://levelcode.org/roadmaps/software-engineer/design-patterns). 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](https://levelcode.org/concepts/yagni)).

OCP is closely tied to the other SOLID principles: [Liskov substitution](https://levelcode.org/concepts/liskov-substitution) makes extensions safe, and [dependency inversion](https://levelcode.org/concepts/dependency-inversion) lets core code depend on the interface rather than every implementation. See the [SOLID lesson](https://levelcode.org/roadmaps/software-engineer/solid).
