Что такое сервис локатор, зачем он нужен и какие у него проблемы?
Что проверяют
Понимаете ли вы разницу между тем, кто отдаёт зависимость, и тем, кто её забирает. Вопрос про локатор почти всегда ведёт к разговору о тестируемости и о том, видно ли зависимости объекта по его интерфейсу.
Как отвечать
Сервис-локатор это реестр, у которого объект сам запрашивает нужную реализацию по типу или ключу. Противоположность ему это внедрение зависимостей: объект получает готовую реализацию снаружи и про реестр ничего не знает.
// зависимость спрятана в теле
final class ProfileViewModel {
private let api = Locator.shared.resolve(APIClient.self)
}
// зависимость видна в контракте
final class ProfileViewModel {
init(api: APIClient) { self.api = api }
}Зачем он нужен: не приходится протаскивать зависимость через пять экранов, реализацию можно подменить в одной точке, он выручает в легаси, где менять инициализаторы дорого, и на необязательных зависимостях.
Что называть проблемами. Зависимость становится невидимой: по инициализатору не понять, что классу нужны сеть и хранилище. Ошибка регистрации превращается из ошибки компиляции в падение при исполнении и зависит от порядка старта. Реестр это глобальное изменяемое состояние, отсюда гонки при регистрации из разных потоков и общее состояние между тестами. Граф зависимостей нельзя проверить сборкой, и разрезать приложение на модули становится сложнее.
Сильный финал это компромисс: локатор уместен в точке сборки приложения, а дальше зависимости лучше передавать явно.
Где спотыкаются
Называют локатор разновидностью внедрения зависимостей. Направления противоположные: при внедрении контракт виден в сигнатуре и проверяется компилятором, при локаторе он спрятан в теле и всплывает только при исполнении.
Говорят, что локатор упрощает тесты. Подменить реализацию он позволяет, но общий реестр приходится сбрасывать между тестами, иначе они начинают зависеть от порядка запуска и плавающе падают при параллельном прогоне.
Прячут обращение к реестру в обёртку над свойством и считают вопрос закрытым. Скрытая зависимость никуда не делась, она лишь стала незаметнее на ревью, а падение из-за незарегистрированного типа теперь случается при первом обращении к свойству.