Одна функция заказа, на которой проявятся все шесть принципов
Возьмём небольшой интернет-магазин. Первая версия умеет посчитать сумму заказа, применить скидку и добавить стоимость доставки. Требование кажется простым, поэтому разработчик пишет всё в одной функции.
function calculateOrder(order) {
let subtotal = 0;
for (const item of order.items) {
subtotal += item.price * item.quantity;
}
let discount = subtotal > 10000 ? subtotal * 0.1 : 0;
let delivery = subtotal > 5000 ? 0 : 500;
return subtotal - discount + delivery;
}Код работает: тестовый заказ выдаёт правильную сумму. Именно в этот момент особенно легко начать "улучшать архитектуру" просто потому, что мы знаем красивые слова. Но сначала стоит увидеть реальные свойства решения. Что здесь уже нормально: формула читается сверху вниз, в ней нет фабрик, контейнеров и абстрактных провайдеров - для первой версии это достоинство, а не недостаток. Что настораживает: функция одновременно знает правила скидки, доставки и структуру заказа. Если эти части начнут меняться независимо, одна функция станет точкой постоянных конфликтов.
Причём проблема не в сегодняшнем коде, а в его траектории.
- Сегодня: одно правило скидки, один способ доставки
- Через месяц: промокоды, категории клиентов, два перевозчика
- Через полгода: маркетинг и логистика меняют правила независимо
Первый навык - не про паттерны. Не спрашивайте, какой паттерн сюда вставить. Спросите, какая часть кода уже создаёт измеримую проблему. Пока проблемы нет - её и не надо "решать" заранее.
Дальше мы будем возвращаться к этой функции в каждой практике и смотреть, какой принцип отвечает на очередное реальное изменение. Начнём с самого раннего вопроса: достаточно ли просто решение.