Можно ли из ViewModel напрямую обращаться к репозиторию или лучше через UseCase
Что проверяют
Есть ли у вас собственная позиция по архитектуре или только выученное «так положено в Clean Architecture». Интервьюер ждёт аргументов в обе стороны и условий, при которых слой UseCase окупается. Следом обычно просят показать, как выглядит хороший UseCase и что в него класть не надо.
Как отвечать
Можно и так, и так. В официальном руководстве Google по архитектуре Android доменный слой прямо назван необязательным: ViewModel может обращаться к репозиторию напрямую, пока логики между ними нет.
UseCase окупается, когда появляется хотя бы одно из условий:
- повторное использование: одна и та же логика нужна нескольким ViewModel, например «получить ленту с учётом блокировок пользователя»;
- комбинация источников: данные собираются из двух-трёх репозиториев, а ViewModel не должна знать, как именно;
- сложные бизнес-правила: расчёты и валидация, которые хочется тестировать отдельно от экрана;
- договорённость команды: на большом проекте единообразие иногда важнее экономии файлов, и правило «ViewModel ходит только в UseCase» принимают сознательно.
Хороший UseCase это один класс на одно действие, имя вида «глагол + сущность + UseCase» (GetUserFeedUseCase), один публичный operator fun invoke, зависимости через конструктор и никакого изменяемого состояния. Он main-safe: переключение на Dispatchers.IO делает репозиторий или сам UseCase, но не ViewModel.
Если UseCase только вызывает repository.getUser() и больше ничего не делает, это лишний слой. Здравая позиция: начинать без него и выносить логику в UseCase, когда она повторяется или разрастается внутри ViewModel.
Где спотыкаются
Отвечают догмой: «всегда через UseCase, иначе нарушается Clean Architecture». Без условий такой ответ показывает, что вы не взвешивали цену: десятки классов-прокладок, которые ничего не делают.
Делают UseCase-менеджер с десятком методов. Это тот же репозиторий под другим именем, и смысл «одно действие на класс» теряется.
Тащат в доменный слой Android-зависимости или сетевые DTO. UseCase, который принимает Context или возвращает модель ответа Retrofit, привязан к фреймворку и перестаёт быть доменной логикой.