Design for Use (DRAFT)
This is a draft rewrite/replacement for Design for Pace of Change.
Design for known use cases over speculative reuse.
Although YAGNI is commonly used when thinking about features and non-functional optimisations, it can conflict with our instincts about what “good” looks like – and what good engineers do – when applied to reuse and elegance. We believe it deserves extra attention in that context. Designing for reuse from the outset, in the absence of well-understood use cases, requires us to make assumptions about what will be valuable at some point in the future. These assumptions usually turn out to be wrong. As well as wasting effort and creating a cost of delay, this can inhibit change by creating unnecessary complexity, dependencies and bottlenecks. Code that is designed for reuse is generally harder to build, maintain and use than code designed for a single purpose1, so we should first establish that there is concrete value in reuse outweighing the costs, and accept duplication until then.
- Identify reuse as it emerges through evolution or modelling the business domain; prefer duplication over premature abstraction until you have evidence it will not constrain the required pace of change.
- Once appropriate abstractions have been established, systems should expose common business functionality through APIs.
- Be sceptical of components that look similar but aren't the same once you consider business use cases and what might trigger them to change and diverge.
- This principle can only be effective if reuse can be enabled in future at a similar cost to today. We must therefore focus on building easy-to-change Evolutionary Systems.
- Sharing domain-specific code libraries between bounded contexts is an anti-pattern and a hazard to be avoided2.
- If reused code becomes a bottleneck, remove the coupling by forking or duplicating the code.
- Technical and operational features such as monitoring, logging, service discovery, authentication & authorisation often need to be implemented consistently across all applications. Use Service Templates to define which libraries should be used by all services1.
1. [Building Evolutionary Architectures: Support Constant Change by Neal Ford, Patrick Kua, and Rebecca Parsons] (http://shop.oreilly.com/product/0636920080237.do) ↩
2. [Domain Driven Design by Eric Evans] (http://dddcommunity.org/book/evans_2003/) ↩