Какой паттерн использовать для передачи данных между модулями без сильной зависимости?
Что проверяют
Умеете ли вы снижать связанность модулей и понимаете ли цену каждого подхода. Интервьюер ждёт не только названия паттернов, но и выбор под ситуацию: соседние компоненты, разные ветки дерева, независимые микрофронтенды. Следом спрашивают, как вы отлаживаете поток событий, когда непонятно, кто что отправил.
Как отвечать
Разложите варианты по степени связанности:
- Observer и Pub/Sub: модуль публикует событие, подписчики реагируют, отправитель о них не знает. В браузере для этого есть
EventTargetиCustomEvent, в приложении подойдёт маленькая шина вродеmitt. В Vue 3 у экземпляра убрали$onи$off, поэтому шину берут внешнюю; - Mediator: центральный объект координирует взаимодействие, модули общаются только с ним. Пример: сложная форма, где поля зависят друг от друга, а правила живут в одном месте;
- общее хранилище: Redux Toolkit, Zustand, Pinia. Модули не знают друг о друге, только о форме состояния и действиях;
- инверсия зависимостей: модуль зависит от интерфейса, реализацию передают снаружи. В React это Context, но он про доставку значения, а не про события, и при частых изменениях перерисовывает всех потребителей;
- между вкладками и микрофронтендами:
BroadcastChannel,postMessageдля iframe, события наwindowс договорённой схемой данных.
Покажите правило выбора: данные, которые нужны многим, держат в хранилище, редкие разовые сигналы отправляют через шину событий, а тесно связанную логику внутри одной фичи собирает Mediator.
Где спотыкаются
Называют Vuex шиной событий. Это хранилище состояния, и для новых проектов на Vue официально рекомендуют Pinia.
Строят всё на глобальной шине. Через полгода никто не знает, кто подписан на user:updated, а забытые отписки дают утечки памяти и двойные обработчики.
Путают Context с менеджером состояния и кладут туда часто меняющиеся данные, после чего тормозит всё дерево под провайдером.