Как реализовать смену сервера для запроса данных с использованием Dependency Injection
Что проверяют
Понимаете ли вы, где в приложении проходит граница между конфигурацией и кодом, и умеете ли внедрить адрес сервера так, чтобы его смена не требовала правок в сетевом слое. Следом обычно спрашивают, как переключать сервер на лету из отладочного меню и как это протестировать.
Как отвечать
Каркас из трёх уровней:
- абстракция: протокол
ServerEnvironmentили структураAPIConfigurationсbaseURL, заголовками и ключами. Сетевой клиент (APIClient) получает её через инициализатор и нигде не хранит адрес строкой; - источник значения: для сборок под разные окружения используют отдельные схемы и
.xcconfig-файлы, значение прокидывается вInfo.plistи читается при старте. Так релизная сборка физически не содержит адресов тестовых стендов; - смена в рантайме: для тестировщиков делают отладочное меню, выбор сохраняется в
UserDefaults. Клиент либо запрашивает текущий адрес у провайдера на каждом запросе, либо корень композиции пересобирает граф зависимостей после переключения.
Собирать зависимости лучше в одном месте, в точке входа @main или в SceneDelegate. Внедрение через инициализатор без контейнера закрывает большинство задач. Если граф большой, подключают Swinject или Factory, а в SwiftUI можно передать конфигурацию через собственный EnvironmentKey.
При переключении сервера нужно сбросить всё, что к нему привязано: токены в Keychain, cookies в HTTPCookieStorage, URLCache и локальный кеш данных. Токен от продакшена тестовый стенд не примет, а старые данные в интерфейсе запутают тестировщика.
Для тестов в клиент передаётся заглушка протокола, а для проверки реальных запросов без сети подменяют URLProtocol в конфигурации URLSession.
Где спотыкаются
Делают NetworkManager.shared с зашитым адресом и называют это DI. Смена сервера превращается в правку константы, а тесты ходят в настоящую сеть.
Оставляют переключатель стендов в сборке для App Store. Меню и адреса нужно закрывать флагом компиляции #if DEBUG или отдельной конфигурацией.
Меняют только baseURL. Запросы уходят на новый сервер со старым токеном, приложение ловит 401 и выкидывает пользователя, хотя проблема в несброшенной сессии.