В индустрии разработки сложилось почти религиозное правило: дублирование кода - это абсолютное зло. Нам с первых дней твердят о принципе
DRY (Don't Repeat Yourself), и любое повторение воспринимается как признак плохого дизайна. Но реальность сложнее черно-белых правил. В некоторых случаях именно дублирование оказывается более прагматичным и безопасным решением, чем искусственно созданная абстракция.
Когда абстракция становится сложнее проблемы:
Классический сценарий: вы видите два похожих фрагмента кода в разных частях приложения. Первая мысль: выделить общую функцию. Но что, если эти фрагменты похожи только сейчас, а их бизнес-логика в будущем будет развиваться по разным направлениям?
Пример из реальной практики: два сервиса обрабатывают пользовательские данные. Оба валидируют email. Казалось бы, идеальный кандидат для общей библиотеки. Но через полгода:
- Первый сервис должен принимать email с кириллическими доменами.
- Второму нужно добавить проверку временных почтовых сервисов.
И вот уже наша «идеальная» абстракция обрастает флагами isCyrillicDomainAllowed и checkDisposableEmail, превращаясь в монстра, который пытается угодить всем и становится понятным только автору.
Дублирование как плата за независимость команд:
В эпоху микросервисной архитектуры этот аспект становится критически важным. Две команды разрабатывают разные сервисы. Обеим нужна аутентификация. Варианты:
- Создать общую библиотеку: требуются общие процессы, синхронизация релизов, согласование изменений.
- Допустить дублирование: каждая команда реализует свою версию, оптимизированную под конкретный контекст.
Иногда второй вариант экономит больше времени и нервов, чем кажется на первый взгляд. Особенно когда команды работают в разных часовых поясах или имеют разные релизные циклы.
Практическое правило трех повторений:
Один из самых полезных эвристических подходов звучит так:
- Первый раз - дублируйте без зазрения совести.
- Второй раз - задумайтесь, но не обязательно действуйте.
- Третий раз - вот теперь пора создавать абстракцию.
Это правило защищает от двух крайностей: хаотичного дублирования всего подряд и преждевременной абстракции, которая часто оказывается сложнее, чем исходная проблема.
Какие виды дублирования действительно опасны, а какие допустимы:
Опасно дублировать:
- Бизнес-правила (особенно финансовые расчеты).
- Критическую логику безопасности.
- Контракты с внешними API.
Допустимо дублировать:
- Вспомогательные утилиты в разных независимых сервисах.
- Простые проверки и валидации.
- Код, который с высокой вероятностью будет меняться в разных направлениях.
Как правильно принимать решение:
Прежде чем бросаться устранять дублирование, задайте себе вопросы:
- Насколько вероятно, что этот код будет меняться одинаково в обоих местах?
- Что дороже: поддерживать две копии или одну сложную абстракцию?
- Насколько тесно связаны модули, содержащие похожий код?
- Будет ли абстракция действительно проще, чем текущее дублирование?
Вывод:
Принцип
DRY - это не императивная команда, а руководство к размышлению. Слепое устранение всех повторений может привести к созданию сложных, перегруженных абстракций, которые труднее понимать и поддерживать, чем исходное дублирование.
Ключевая мысль: дублирование - это не всегда антипаттерн. Иногда это сознательный архитектурный выбор, позволяющий сохранить простоту, независимость и скорость разработки. Настоящее искусство проектирования заключается не в следовании догмам, а в способности взвешивать компромиссы в конкретном контексте.