Ответ
Dependency Injection (DI) — это паттерн, который я активно использую для создания тестируемого и слабосвязанного кода. Вместо того чтобы класс сам создавал свои зависимости, он получает их извне.
Основные подходы в Dart/Flutter:
-
Constructor Injection (наиболее частый в моём коде): Зависимости передаются через конструктор.
class AuthService { final ApiClient _client; final StorageRepository _storage; AuthService(this._client, this._storage); // Зависимости инжектятся Future<void> login() async { final token = await _client.post('/login'); await _storage.saveToken(token); } } -
Использование пакетов для DI: Для больших проектов я использую
get_itв связке сinjectableдля автоматической генерации регистрации.// Настройка locator (get_it) final getIt = GetIt.instance; @injectable class ApiClient { ... } @injectable class AuthService { AuthService(this.apiClient); final ApiClient apiClient; } // Где-то в коде: final authService = getIt<AuthService>(); // Все зависимости разрешены автоматически
Преимущества, которые я получил на практике:
- Тестируемость: Легко подменить
ApiClientмоком в unit-тестах. - Гибкость: Замена реализации (например,
FirebaseStorageRepositoryнаHiveStorageRepository) происходит в одном месте — контейнере DI. - Чистая архитектура: Классы перестают знать о способе создания своих зависимостей.
Во Flutter DI часто реализуется через виджеты провайдеры (Provider, Riverpod), которые по сути являются контейнерами зависимостей для поддерева виджетов.