Интервью-вопрос
Что такое DRY
DRY помогает держать одно правило в одном месте и не чинить один и тот же баг по всему проекту. Главное не путать его с запретом на любые похожие строки.
- Добавлен
- Редакция
Подготовьте короткий ответ и пару деталей на случай уточняющих вопросов.
Мини-квиз
Проверка перед разбором
Несколько быстрых вопросов перед разбором. Так проще поймать места, которые только кажутся понятными.
Вопрос 1 из 60 правильно
Разбор
Разобраться, а не зазубрить
Дальше разбираем суть, типичные уточнения и места, где легко сказать лишнее или перепутать термины.
Базовая идея
DRY расшифровывается как Don't Repeat Yourself. На интервью важно не остановиться на фразе "не повторяй код". Точнее сказать так: не дублируйте знание о системе.
Знанием во frontend-проекте может быть правило валидации, формат денег, путь к API, список статусов заказа, способ нормализовать ответ сервера, логика доступа к кнопке или правила аналитики. Если такое знание скопировано в несколько мест, при изменении одно место легко забыть. В итоге пользователь видит разные ошибки, разные ограничения формы или неактуальный UI.
Хорошая короткая формулировка для интервью:
DRY для меня не про механическое удаление похожих строк. Это про один источник правды для правила или логики. Я выношу повторение, когда оно имеет один смысл и должно меняться одинаково.
Где это видно во frontend
Типичный пример: одна и та же проверка email на разных экранах. Если скопировать регулярное выражение в регистрацию, профиль и восстановление пароля, потом легко обновить только один экран. Пользователь получит разные правила в разных местах.
Плохой вариант:
// Плохо: одно правило размазано по разным компонентам
function SignupForm({ email }: { email: string }) {
const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
return isValid ? null : <p>Введите email</p>;
}
function ProfileForm({ email }: { email: string }) {
const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
return isValid ? null : <p>Email указан неверно</p>;
}Более безопасно вынести правило и переиспользовать его:
export function isValidEmail(email: string) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}Теперь при изменении правила вы меняете одну функцию. Тексты ошибок могут оставаться разными, потому что это уже не обязательно то же самое знание. Один экран может говорить коротко, другой может давать подробную подсказку.
DRY в сетевых вызовах и UI-состояниях
Повторяющиеся запросы тоже часто хочется вынести. Это нормально, если вы не выкидываете состояния, которые нужны экрану.
Плохой вариант:
function UsersPage() {
const [users, setUsers] = useState<User[]>([]);
useEffect(() => {
fetch("/api/users")
.then((response) => response.json())
.then(setUsers);
}, []);
return <UserList users={users} />;
}Что сломается: при медленной сети пользователь видит пустой список без объяснения. Ошибка запроса пропадает. При смене параметров старый ответ может перезаписать новый. Если компонент размонтировался, запрос все равно завершится и попробует обновить состояние.
Безопаснее выносить не просто fetch, а понятный контракт для UI: data, loading, error, пустое состояние и отмену через AbortController. Тогда DRY убирает копипасту, но не прячет поведение, от которого зависит экран.
Когда выносить повторение
На интервью полезно показать критерий, а не только определение. Повторение стоит выносить, когда оно несет один смысл, используется в нескольких местах и должно меняться одинаково. Если при изменении требования вы будете одинаково править несколько файлов, это почти всегда сигнал для DRY.
Но похожий код не всегда надо объединять. Две карточки товара и профиля могут иметь похожую верстку, но разные причины изменения. У товара появится цена, скидка и состояние корзины. У профиля появится приватность, роль и статус подписки. Общая карточка с десятком пропсов может стать хуже, чем два понятных компонента.
Как решить, применять ли DRY
Вынесите в функцию, схему, хук или модуль с одним источником правды.Не спешите объединять. Сначала проверьте, будут ли эти места меняться одинаково.Остановитесь и разделите ответственность. Возможно, нужна композиция, а не один универсальный компонент.Это хороший сигнал для DRY. Вынесите правило и покройте его тестом.Вынесите общий слой аккуратно. Контракт должен явно возвращать состояния UI и не допускать race condition.Главная ловушка: over-DRY
Over-DRY начинается там, где вы объединяете не общее знание, а просто похожую форму кода. Сначала компонент выглядит аккуратно. Потом в него добавляют variant, mode, withActions, isCheckout, isProfile. Через несколько задач никто уже не понимает, какие сочетания пропсов допустимы.
Практический риск простой: изменение для одного экрана ломает другой. Команда начинает бояться править общий компонент, делает обходные костыли или копирует его обратно. Поэтому сильный ответ не должен звучать как "дублирование всегда зло". Лучше сказать, что вы ищете баланс между единым источником правды и простой связностью.
Как говорить про DRY на ревью и в работе
Хорошая формулировка на ревью звучит спокойно и проверяемо:
Здесь повторяется не просто JSX, а правило расчета доступности кнопки. Если оно изменится, придется править три места. Я бы вынес это в функцию или хук и добавил тест на основные состояния.
И другая ситуация:
Эти компоненты похожи визуально, но отвечают за разные сценарии. Я бы пока не объединял их в общий компонент. Если после еще пары задач паттерн станет стабильным, можно вынести общую часть.
Такой ответ показывает зрелость. Вы не применяете принцип автоматически. Вы оцениваете последствия для изменений, тестов и читабельности.
Практический вывод
Если вас спрашивают "Что такое DRY", отвечайте в три шага. Сначала дайте определение: один источник правды для одного знания. Потом приведите frontend-пример: валидация, хук, компонент, константы API, обработка запроса или форматирование данных. Затем добавьте ограничение: случайное сходство кода не всегда надо абстрагировать.
Самый безопасный вывод: DRY уменьшает рассинхрон и стоимость изменений, но плохая абстракция создает связанность. Поэтому выносить нужно не все похожее, а то, что имеет общий смысл и общую причину изменения.
Частые ошибки
Где обычно ошибаются
Проверьте формулировки, которые звучат уверенно, но на интервью быстро выдают пробелы.
- 1
Считать DRY борьбой с любыми похожими строками
Похожие строки не всегда означают одно и то же знание. Две карточки могут сегодня выглядеть одинаково, а завтра одна получит другую аналитику, доступность или логику загрузки. Надежнее говорить, что DRY нужен там, где повторяется смысл или правило.
- 2
Делать универсальный компонент слишком рано
Ранний общий компонент часто обрастает пропсами
isCompact,withIcon,modeи исключениями. Такой код сложнее читать. Изменение одного сценария может сломать другой. Лучше сначала увидеть стабильный паттерн, а потом выделить компонент или композицию. - 3
Выносить UI и бизнес-правило в одну абстракцию
Если компонент одновременно рисует форму, валидирует данные и знает API-контракт, его трудно переиспользовать. Изменение дизайна может задеть валидацию. Изменение правила может сломать UI. Часто лучше разделить схему, хук и визуальный компонент.
- 4
Дублировать контракт с сервером в нескольких местах
Если URL, статусы, формат ошибки или маппинг ответа разбросаны по экранам, один экран может продолжить жить по старому контракту. Так появляются разные сообщения об ошибках, неверная аналитика и баги при изменении API. Лучше держать клиентский слой или общий адаптер ответа.
- 5
Прятать сетевые состояния в слишком общий хук
Желание убрать повторяющийся
fetchполезно, но общий хук не должен скрывать важные состояния. Если он не возвращаетloading,error, пустой результат и способ отменить запрос, экран начнет показывать старые данные, мигать или перетирать свежий ответ устаревшим. Безопаснее держать общий клиент API отдельно, а хук делать с явным контрактом для UI. - 6
Удалять дублирование без тестов
Рефакторинг под DRY кажется безопасным, но общая функция меняет сразу несколько сценариев. Без тестов легко сломать крайний случай, который раньше жил в отдельной ветке. Перед выносом полезно зафиксировать поведение тестами или хотя бы проверочным списком сценариев.
Follow-up
Что могут спросить дальше
Короткие ответы на вопросы, которыми проверяют, понимаете ли вы границы DRY и риски лишней абстракции.
Живые ответы
Видео с похожим вопросом
Если найдем публичные интервью с таким вопросом, добавим их сюда. Их удобно смотреть после теории, чтобы свериться с живыми ответами.
Пока видео нет. Когда появятся подходящие публичные интервью, добавим их в этот блок, чтобы можно было сравнить разбор с тем, как отвечают реальные кандидаты.
Что такое чистая функция 😎
Чистая функция возвращает один и тот же результат для одинаковых входных данных и не создает побочных эффектов. Разбираем, как объяснить это на интервью, где проходит граница и почему это важно во frontend-коде.
Что такое Agile 😎
Agile это набор ценностей и принципов для итеративной разработки с регулярной обратной связью. На странице разбираем, как ответить без путаницы со Scrum и что это значит для frontend-разработчика.