DRY, KISS и YAGNI
Зачем это на интервью
Эти принципы помогают обсуждать качество решения после того, как оно работает. Интервьюер ожидает, что E4 отличит дублирование знания от похожего кода, выберет простой путь и объяснит, почему не добавляет гипотетическую расширяемость. Это особенно важно в задаче, где «красивый» паттерн делает изменение менее прозрачным.
Минимум для E4
- Отличать DRY про единый источник знания от механического удаления одинаковых строк.
- Выбирать KISS: решение с наименьшей случайной сложностью, понятное следующему читателю.
- Применять YAGNI: не реализовывать возможность без текущего проверяемого требования.
- Рефакторить повтор только после понимания, что части меняются вместе.
DRY (Don’t Repeat Yourself) запрещает несколько независимых представлений одного правила. Например, лимит кредита, зашитый и в валидаторе, и в SQL-предикате, расходится при изменении политики. Два похожих HTTP-обработчика не обязательно нарушают DRY: их сходство может быть случайным, а будущие изменения — разными.
KISS (Keep It Simple, Stupid) призывает минимизировать случайную сложность: уровни косвенности, состояния, неявные соглашения и магию конфигурации. Простота не означает примитивность; корректный алгоритм с явными инвариантами лучше короткого, но хрупкого кода.
YAGNI (You Aren’t Gonna Need It) требует реализовывать подтверждённую потребность, а не прогноз. Он не запрещает оставлять точку расширения, если она уже нужна текущему сценарию, например передать Clock для детерминированного теста.
Углубление для E5/Senior
E5 рассматривает эти правила вместе. Раннее объединение дублирующегося кода может нарушить KISS, а отказ от абстракции может создать дорогую повторяемую работу. Решение принимают по траектории изменений: есть ли одинаковая бизнес-инварианта, кто владеет ей, как часто она меняется и насколько опасно расхождение.
Полезна «правила трёх» как сигнал к исследованию, а не закон: после третьего похожего случая собрать факты, выделить общую семантику и сохранить различия явными. Для публичных API YAGNI особенно ценен: каждое поле и флаг становятся обязательством совместимости. Удалить неиспользованную возможность после релиза часто дороже, чем добавить её позже.
Ключевые понятия
| Принцип | Защищает от | Вопрос перед изменением |
|---|---|---|
| DRY | Расхождения бизнес-правил | Это одно и то же знание или только похожая форма? |
| KISS | Случайной сложности | Можно ли объяснить поток выполнения без скрытой магии? |
| YAGNI | Платы за неиспользуемую возможность | Какое текущее требование оправдывает этот код? |
Пример DRY — один конструктор доменного правила, используемый на границе ввода и в прикладном сервисе:
func ValidateQuantity(qty int) error {
if qty < 1 || qty > 100 {
return fmt.Errorf("quantity must be in [1, 100]")
}
return nil
}Не переносите это правило автоматически в базу данных: БД может быть последней защитой целостности и потребовать отдельного ограничения. DRY здесь означает согласованную политику и тесты, а не отсутствие повторения на разных уровнях.
Типовые вопросы
- Почему два одинаковых фрагмента не всегда нужно объединять?
- Они могут выражать разные доменные причины и должны иметь возможность изменяться независимо.
- Что считать «простым» решением?
- То, у которого понятны данные, порядок выполнения, ошибки и границы; число строк вторично.
- Когда YAGNI не применяют буквально?
- Когда требование уже включает надёжность, безопасность или тестируемость, например таймауты для внешнего вызова.
- Как понять, что абстракция преждевременна?
- У неё нет второго реального клиента, контракт описывает догадки, а изменение одного случая требует объяснять общий механизм.
- Как связаны DRY и copy-paste?
- Copy-paste — лишь возможный симптом; нарушением становится дублирование одного изменяемого знания.
- Допустимы ли feature flags с точки зрения YAGNI?
- Да, если они нужны для безопасного rollout сейчас и имеют владельца, срок удаления и наблюдаемость.
Практика
- Найдите два похожих обработчика создания сущности и выпишите, какие правила у них общие, а какие разные.
- Критерии готовности: общее правило имеет один владелец и тест; различия остались в вызывающих сценариях; нет абстракции с параметрами, описывающими все будущие варианты.
- Спроектируйте API экспорта отчёта только для CSV, хотя в бэклоге есть PDF.
- Критерии готовности: контракт не содержит неиспользуемого
format; добавление PDF позже локализуется в одном месте; решение и ограничение задокументированы в тесте или ADR.
- Критерии готовности: контракт не содержит неиспользуемого
Частые ошибки и ловушки
- Объединять одинаковые строки, игнорируя разные инварианты и владельцев.
- Оправдывать сложную архитектуру словом «масштабирование» без измеримого сценария роста.
- Использовать YAGNI, чтобы не добавить обязательную валидацию, метрики или обработку ошибок.
- Создавать универсальный helper с десятком булевых параметров вместо двух ясных функций.
- Не удалять временную универсальность после изменения требований.
Связанные темы
Источники
- Andy Hunt, Dave Thomas. The Pragmatic Programmer, 20th Anniversary Edition, 2019.
- Kent Beck. Extreme Programming Explained, 2nd ed., 2004.
- Martin Fowler. Rule of Three.