Flexibility lets a design accommodate variation or alternative implementations without extensive structural change. Abstractions and extension points let independent parts evolve while keeping new functionality out of increasingly complex existing code. section 5.0 section 5.1
Add an abstraction early when the need for variation is already clear, even with only one or two implementations. Otherwise, postponing flexibility can merely delay an inevitable change and make it more expensive. section 5.3.4
From branching variations to extension points
A class with roughly 40 conditional blocks, each handling a feature variation, became difficult to test and maintain. Refactoring each variant behind an interface and sharing common behavior through a Template Method-style structure reduced duplication. The same principle applies at module boundaries: a payment API can support one-off, recurring, or combined charges without requiring the owning team to change for every new product. section 5.1 section 7.2.3
Design for plausible future users without abstracting arbitrarily. A registration API is more adaptable than a hardcoded list of modules because new participants can join without changing the module. Flexibility still costs complexity, so choose the tradeoff that fits the problem rather than pursuing elegance for its own sake. section 7.2.4 section 5.3.1
Use the three-rule decision aid to judge whether an abstraction or extension point earns its added complexity. section 5.3.1








