РАЗРАБОТКА

Stack Overflow Blog призвал не спешить с переиспользуемыми компонентами

Три похожих интерфейса могут стать ловушкой: Stack Overflow Blog объяснил, почему преждевременная абстракция обходится командам дороже дублирования.

✍️ Редакция iTech News | 06.11.2026 | ⏱ 3 мин | Источник: Stack Overflow Blog
Stack Overflow Blog призвал не спешить с переиспользуемыми компонентами

Три почти одинаковых экрана не всегда нужно сводить к одному «универсальному» компоненту: преждевременная абстракция может сделать разработку медленнее, тестирование дороже, а согласования — бесконечными. Такой вывод разбирает Stack Overflow Blog на примере интерфейсов для подтверждения, изменения и переноса объектов — сценариев, которые внешне похожи, но меняются по разным бизнес-причинам.

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

Проблема проявилась не в первом релизе, а через несколько недель. Одобрение оказалось обещанием на будущее: пользователь подтверждает, что объект понадобится ему позже. Изменение настроек применяется сразу. Перенос зависит от внешней системы, которая способна отклонить запрос. У процессов различались обработка частичных ошибок, требования к аудиту и владельцы решений. Общий визуальный контур скрыл эти различия, но никуда их не убрал.

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

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

Предложенное правило простое: не выносить похожий код в общий слой, пока один и тот же паттерн не повторился трижды по одной причине. Автор опирается на «правило трёх», которое связывают с Доном Робертсом и книгой Мартина Фаулера Refactoring: первый повтор допустим, второй вызывает неудобство, третий уже повод для рефакторинга. В той же логике Сэнди Метц предупреждала, что дублирование дешевле ошибочной абстракции, а подход AHA Кента С. Доддса призывает избегать поспешных обобщений.

Ключевой тест здесь не количество одинаковых строк, а причина будущего изменения. Формат даты разумно вынести в общую функцию: решение о том, как показывать даты, почти наверняка затронет все экраны одновременно. Но две похожие отправки формы могут меняться независимо: одна зависит от политики одобрения, другая — от правил валидации. Если на вопрос «с кем придётся согласовывать это изменение?» для разных копий получаются разные ответы, перед командой не дублирование, а совпадение формы.

Это не аргумент против любого переиспользования. С первого дня полезно делить примитивы интерфейса — кнопки, поля ввода и контейнеры, — дизайн-токены, доступность диалогов, клавиатурную навигацию и работу со стандартами вроде форматов даты, валют или протокольных клиентов. У таких частей обычно есть внешний источник формы, один владелец изменений и минимум прикладной логики. Хороший компонент описывает, что отрисовать: размер, тон, дочерние элементы. Тревожный компонент описывает ситуацию: режим, вариант, особый случай.

Если преждевременная абстракция уже попала в кодовую базу, автор советует начать с шага, который кажется регрессом: вернуть общий модуль в каждый сценарий, убрать неиспользуемые ветки и дать потокам развиваться отдельно. После стабилизации можно снова выделить небольшие действительно общие части — например, таблицу или форматирование дат. Вопрос для ревью остаётся неприятно полезным: какой флаг в вашем компоненте существует только ради одного вызывающего кода и почему его владелец не может менять этот сценарий самостоятельно?

Поделиться: Telegram X LinkedIn