> Использовали ли паттерны Router и Coordinator (iOS, Swift)

Уровень: senior · Роль: mobile · Категория: Технические вопросы

Компании: КРЕЙТЕКС

Стек: iOS, Swift

> Пример ответа

Короткий ответ

Да, использовал оба паттерна в iOS-проектах. Router применял для инкапсуляции навигационной логики и уменьшения связанности между экранами, Coordinator - для управления потоком (flow) и жизненным циклом навигации. На практике часто комбинировал их: Coordinator отвечал за сценарий, Router - за конкретные переходы. Это позволяло переиспользовать экраны в разных контекстах и упрощало тестирование навигации.

Подробное объяснение

Router - это объект, который знает, как выполнить конкретный переход: push, present, pop, dismiss. Он скрывает от вызывающей стороны детали навигации, например, какой именно контроллер нужно создать и с какими параметрами. Router обычно привязан к конкретному экрану или модулю.

Coordinator - более высокоуровневый паттерн. Он управляет целым сценарием: например, onboarding, авторизация или создание заказа. Coordinator создаёт и связывает экраны, решает, когда и куда переходить, обрабатывает завершение flow. Он владеет navigation controller или tab bar controller.

Разница в уровне абстракции: Router отвечает на вопрос "как перейти", Coordinator - "куда и зачем переходить". Coordinator может использовать несколько Router'ов для разных частей сценария.

В Swift-проектах часто используют протоколы для обоих паттернов, чтобы упростить мокирование и тестирование. Например:

SWIFT
protocol AuthRouting: AnyObject {
func showLogin()
func showRegistration()
func showForgotPassword()
}

Coordinator при этом реализует этот протокол или делегирует конкретным Router'ам.

На практике

В реальных проектах я предпочитаю Coordinator как основной паттерн для навигации, а Router - как вспомогательный для переиспользуемых модулей. Например, если у нас есть модуль профиля, который открывается из разных мест приложения, я создаю ProfileRouter, который умеет показывать профиль с нужными параметрами. Coordinator'ы верхнего уровня вызывают этот Router.

Для небольших приложений Coordinator может быть избыточен - достаточно Router'ов. Для крупных - Coordinator обязателен, иначе навигация размазывается по контроллерам и становится неуправляемой.

Важно не путать Router с Coordinator в реализации: Router не должен решать, когда переходить, только как. Coordinator не должен знать, как именно устроен переход внутри Router'а.

Пример кода

SWIFT
// Router для модуля профиля
protocol ProfileRouting: AnyObject {
func showProfile(userID: String)
}
final class ProfileRouter: ProfileRouting {
private weak var navigationController: UINavigationController?
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func showProfile(userID: String) {
let vc = ProfileViewController(userID: userID)
navigationController?.pushViewController(vc, animated: true)
}
}
// Coordinator для авторизации
protocol AuthCoordinatorDelegate: AnyObject {
func authCoordinatorDidFinish(_ coordinator: AuthCoordinator)
}
final class AuthCoordinator {
private let navigationController: UINavigationController
private let profileRouter: ProfileRouting
weak var delegate: AuthCoordinatorDelegate?
init(navigationController: UINavigationController, profileRouter: ProfileRouting) {
self.navigationController = navigationController
self.profileRouter = profileRouter
}
func start() {
showLogin()
}
private func showLogin() {
let loginVC = LoginViewController()
loginVC.onSuccess = { [weak self] userID in
self?.profileRouter.showProfile(userID: userID)
}
navigationController.pushViewController(loginVC, animated: true)
}
}

Как отвечать на собеседовании

Начните с чёткого определения обоих паттернов и их различий. Затем приведите пример из практики: где применяли Router, где Coordinator, почему выбрали такую комбинацию. Обязательно упомяните trade-off: Coordinator добавляет код и сложность, но окупается на больших проектах. Если спросят про альтернативы - скажите про SwiftUI и NavigationStack, но отметьте, что паттерны остаются актуальными для UIKit и гибридных проектов.

Что проверяет интервьюер

  • Понимание разницы между Router и Coordinator, а не просто знание названий.
  • Умение обосновать выбор паттерна под конкретную задачу.
  • Понимание, как паттерны влияют на тестируемость и переиспользование кода.
  • Знание ограничений и недостатков каждого подхода.
  • Способность спроектировать навигацию в незнакомом сценарии.

Типичные ошибки

  • Путаница между Router и Coordinator: называют Router'ом всё подряд.
  • Утверждение, что Coordinator - это просто обёртка над Router, без объяснения разницы в ответственности.
  • Игнорирование тестируемости: не упоминают протоколы и моки.
  • Чрезмерное усложнение: Coordinator на каждый чих, даже для одного экрана.
  • Отсутствие примера из реального проекта - сразу видно, что паттерн не использовался в боевой разработке.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью