Chapter 9

Duplicated Knowledge vs Coincidentally Similar Code

The store adds free delivery for regular customers. The condition looks like the discount: both functions check the amount and the customer type. The temptation arises to merge them into a universal handler - here's how that looks.

TypeScript
function applyRule(amount, customer, mode, threshold, rate, freeValue) {
  if (mode === "discount") { /* ... */ }
  if (mode === "delivery") { /* ... */ }
}

// One file, but two reasons to change

One file, but two reasons to change: discounts belong to marketing, delivery to logistics. They may look the same today and diverge already in the next release, while a shared function would bind independent rules. A deliberate split keeps them separate.

TypeScript
const discount = calculateDiscount(subtotal, customer);
const delivery = calculateDelivery(subtotal, customer);

return subtotal - discount + delivery;

// Similar code is acceptable
// Independent rules stay independent

Two tests tell duplicated knowledge from coincidentally similar code. The DRY test: imagine a requirement change - if both fragments must always change together, it's probably one piece of knowledge; if one can change without the other, the similarity is still external. The AHA test: look at the change history - an abstraction is reliable when the repetition survived several real changes and the shared part stayed shared.

And how knowledge actually reveals itself over time shows on the version trajectory.

  1. Version 1: the two fragments look identical
  2. Version 2: delivery gets regional rules, the discount doesn't change
  3. Version 3: only money rounding repeats - extract it
The key question is about the reason, not the operators. Do these fragments have one reason to change, or do they just use the same operators? The first is grounds to merge, the second is grounds to leave them as is and extract only the little that's truly shared (money rounding, for instance).

Duplication is covered. Next are boundaries: SoC and SOLID become useful when parts of the system get different owners.

Links