An extension point is a deliberate contract or location where new behavior can be added without repeatedly changing existing code. It controls growth: instead of expanding a class with more branches for every variation, move variability behind an abstraction that clients can plug into. The goal is not abstraction for its own sake, but maintainable flexibility as business rules evolve. section 2.3 section 5.1
Pluggable discount rules
A basket can use a Discount abstraction while accepting many discount rules, such as seasonal offers or product-specific promotions. The abstraction names the shared job; the extension point supplies the mechanism for adding, removing, or combining rules without rewriting basket pricing code. Similar flexibility suits salary components, tax calculations, and framework security filters. section 5.0 section 5.1.2
Design an extension point around likely change, while keeping its cost visible:
- Identify a feature with recurring variations or rules. A few conditionals may be fine; a growing collection of similar branches is a signal that existing code is becoming the extension mechanism. section 5.1
- Design both the abstraction and the way clients will use it. An interface alone may not be enough when callers must plug multiple implementations into a workflow. section 5.1.2
- Prefer a simple contract over speculative elegance. Extension points ease future additions but also add code complexity, so weigh flexibility against the actual need. section 5.3.1 section 5.5
- Refine the contract from real usage. Changing widely used interfaces can break dependents, so evolve carefully and preserve backward compatibility when necessary. section 5.1.4
Extension points also operate at module boundaries. A clean module interface lets other teams customize behavior without modifying the module or synchronizing for every small change. A billing API, for example, can let product teams configure one-off and recurring payments, allowing new products to ship without repeated billing-team changes. Stable promises, hidden internals, and clear ownership keep this flexibility from becoming coupling. section 7.2 section 7.2.3 section 7.5
Use the decision aid to weigh whether anticipated flexibility justifies introducing an abstraction or extension point now. section 5.3.1
An extension point is worthwhile when it gives a changing concern a small, usable place to evolve independently. It is less useful when variability is uncertain and the added contract merely makes a simple design harder to understand. When flexibility is clearly needed from the start, beginning with one or two implementations can still be the cheaper choice. section 5.3.4 section 5.5
