// SOLID & Principles · 06
DRY
Don't Repeat Yourself: each piece of knowledge lives in one place.
How it fits together
- VAT rate change publishes / notifies OrderService (edit 1)
- VAT rate change publishes / notifies InvoiceService (edit 2)
- VAT rate change publishes / notifies CartTotals (edit 3)
- OrderService uses / calls VatCalculator (Apply(net))
- InvoiceService uses / calls VatCalculator (Apply(net))
- CartTotals uses / calls VatCalculator (Apply(net))
Spot it
- A rule change needs edits in several files
- Validation differs between API and UI
- A bug fixed in one copy survives in another
It costs
Merging look-alike code couples things that should change independently.
In code
public sealed class VatCalculator{ public const decimal Rate = 0.19m; public decimal Apply(decimal net) => net * Rate;}public sealed class OrderService(VatCalculator vat){ public decimal Total(IEnumerable<OrderLine> lines) { var net = lines.Sum(line => line.Net); return net + vat.Apply(net); }}Go deeperThe full explanation and what to ask for · 1 min readExpandCollapse
Hunt and Thomas defined it in The Pragmatic Programmer: every piece of knowledge must have a single, unambiguous, authoritative representation within a system. It is about knowledge, not text.
Two blocks that look the same but answer to different rules are incidental duplication. Merging them produces a shared helper full of flags and branches that every caller is afraid to touch.
A useful boundary: deduplicate freely within a bounded context, reluctantly across them. The rule of three helps: wait for the third copy before abstracting.
Ask for it
- single source of truth
- knowledge duplication
- incidental duplication
- rule of three
- shared kernel
Find where the VAT calculation rule is duplicated across services and the frontend. Consolidate it into one source of truth, a single tested class or shared contract, and leave alone code that merely looks similar but changes for different reasons.