В чем разница между Use case и Interactor?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между Use Case и Interactor в iOS-архитектурах
В контексте чистой архитектуры (Clean Architecture) и таких её производных, как VIPER или VIP, понятия Use Case и Interactor тесно связаны, но имеют важные концептуальные различия. Оба элемента отвечают за бизнес-логику, но их роль и зона ответственности различаются.
Концептуальное определение
Use Case (Сценарий использования) — это абстрактное описание конкретного бизнес-правила или действия, которое система может выполнить. Он отвечает на вопрос "что?" — что должно быть сделано, без привязки к реализации. Use Case инкапсулирует одну бизнес-задачу, например: "Получить список пользователей", "Создать заказ", "Отправить уведомление". Он представляет собой контракт или спецификацию поведения.
Interactor (Интерактор) — это конкретная реализация одного или нескольких Use Case на уровне бизнес-логики. Он отвечает на вопрос "как?" — как именно выполнить бизнес-задачу, координируя работу сущностей (Entities) и внешних зависимостей. В архитектуре VIPER/VIP Interactor — это класс, который выполняет Use Case, работая с сервисами, репозиториями и другими компонентами.
Ключевые различия
| Аспект | Use Case | Interactor |
|---|---|---|
| Уровень абстракции | Абстрактный, декларативный | Конкретный, императивный |
| Роль | Спецификация бизнес-правила | Исполнитель бизнес-правила |
| Реализация | Может быть протоколом, структурой или даже описанием в документации | Конкретный класс (обычно) |
| Зависимости | Не имеет зависимостей (только описание) | Зависит от репозиториев, сервисов, сетевых слоёв |
| Количество на задачу | Один Use Case = одна задача | Один Interactor может реализовывать несколько Use Case (хотя это нежелательно) |
Пример кода
Рассмотрим пример с получением списка пользователей.
Use Case как протокол (абстракция):
// Use Case описывает ЧТО нужно сделать
protocol FetchUsersUseCase {
func execute(completion: @escaping (Result<[User], Error>) -> Void)
}
Interactor как реализация Use Case:
// Interactor реализует КАК это сделать
class UsersInteractor: FetchUsersUseCase {
private let userRepository: UserRepositoryProtocol
private let networkService: NetworkServiceProtocol
init(userRepository: UserRepositoryProtocol,
networkService: NetworkServiceProtocol) {
self.userRepository = userRepository
self.networkService = networkService
}
func execute(completion: @escaping (Result<[User], Error>) -> Void) {
// Бизнес-логика: сначала пробуем получить из кэша, потом из сети
userRepository.fetchCachedUsers { [weak self] cachedUsers in
if !cachedUsers.isEmpty {
completion(.success(cachedUsers))
}
self?.networkService.fetchUsers { result in
switch result {
case .success(let users):
self?.userRepository.saveUsers(users)
completion(.success(users))
case .failure(let error):
completion(.failure(error))
}
}
}
}
}
Практические аспекты в iOS-разработке
-
Тестируемость: Use Case как протокол позволяет легко создавать моки и стабы для тестирования. Interactor, реализующий Use Case, тестируется изолированно через его зависимости.
-
Принцип единой ответственности (SRP): Идеально, когда один Interactor реализует один Use Case. Это делает код более поддерживаемым и понятным.
-
Архитектурные паттерны:
- В VIPER Interactor — обязательный компонент, который содержит бизнес-логику.
- В Clean Architecture Use Case — центральная концепция, а Interactor может рассматриваться как её реализация.
- В MVVM + Coordinators Use Case часто реализуется в ViewModel или отдельном сервисе.
-
Управление зависимостями: Interactor обычно получает зависимости через внедрение зависимостей (DI), что соответствует принципу инверсии зависимостей (DIP).
Рекомендации по использованию
- Создавайте Use Case для каждой бизнес-операции, даже если она кажется простой. Это улучшает тестируемость и переиспользование.
- Инжектируйте зависимости в Interactor через инициализатор, а не создавайте внутри.
- Разделяйте Interactor'ы по функциональным областям:
AuthInteractor,PaymentInteractor,ProfileInteractor. - Используйте протоколы для Use Case, чтобы обеспечить возможность подмены реализации.
Заключение
Use Case и Interactor — это два взаимодополняющих понятия в современной iOS-архитектуре. Use Case определяет что нужно сделать, а Interactor реализует как это сделать. Их разделение позволяет создавать гибкую, тестируемую и поддерживаемую бизнес-логику, соответствующую принципам чистой архитектуры. Правильное использование этих паттернов значительно упрощает масштабирование приложения и работу в команде.