Глава 9

Дублирование знания против похожего кода

В магазине появляется бесплатная доставка постоянным клиентам. Условие похоже на скидку: обе функции проверяют сумму и тип клиента. Возникает соблазн объединить их в универсальный обработчик - и вот как это выглядит.

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

// One file, but two reasons to change

Один файл, но две причины меняться: скидки принадлежат маркетингу, доставка - логистике. Они могут выглядеть одинаково сегодня и разойтись уже в следующем релизе, а общая функция свяжет независимые правила. Осознанное разделение оставляет их раздельными.

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

return subtotal - discount + delivery;

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

Отличить дублирование знания от случайно похожего кода помогают два теста. Тест на DRY: представьте изменение требования - если оба фрагмента всегда должны меняться вместе, вероятно, это одно знание; если один может измениться без второго, сходство пока внешнее. Тест на AHA: посмотрите на историю изменений - абстракция надёжна, когда повторение пережило несколько реальных изменений и общая часть осталась общей.

А как знание действительно проявляется со временем - видно на траектории версий.

  1. Версия 1: два фрагмента выглядят одинаково
  2. Версия 2: доставка получает правила по регионам, скидка не меняется
  3. Версия 3: повторяется только округление денег - выносим его
Ключевой вопрос - про причину, а не про операторы. У этих фрагментов одна причина для изменения или они просто используют одинаковые операторы? Первое - повод объединить, второе - повод оставить как есть и вынести лишь то немногое, что реально общее (например, округление денег).

Дублирование мы разобрали. Дальше - границы: SoC и SOLID становятся полезны, когда у частей системы появляются разные владельцы.

Ссылки