Какие модели используются в репозитории и интерфейсах в архитектуре приложения
Что проверяют
Понимаете ли вы, что в слоистой архитектуре у одной сущности несколько представлений, и зачем их разделять. Следом обычно просят показать, где живут мапперы и что именно возвращает репозиторий: Flow, suspend-функцию или Result.
Как отвечать
Опишите модели по слоям, как в рекомендациях Google по архитектуре Android и в Clean Architecture:
- DTO сетевого слоя: классы под формат API, с аннотациями
@Serializableили@Json. Повторяют ответ сервера со всеми его странностями, nullable-полями и snake_case; - Entity базы: классы с
@Entityдля Room. Устроены под хранение: плоские, с первичным ключом и связями; - доменная модель: чистый Kotlin без зависимостей от Android, Retrofit и Room. Её отдаёт репозиторий и используют use case;
- UI-модель или
UiState: то, что нужно экрану, уже подготовленное: строки, флаги загрузки и ошибки. Обычноdata class, который ViewModel отдаёт черезStateFlow.
Между слоями стоят мапперы, чаще функции-расширения вроде UserDto.toDomain(). Так изменение API ломает один маппер, а не половину экранов.
Интерфейсы нужны на двух границах. UserRepository объявлен интерфейсом, реализация UserRepositoryImpl связывается через Hilt @Binds, и ViewModel в тестах получает фейк. Внутри репозитория источники тоже за интерфейсами: UserRemoteDataSource и UserLocalDataSource. Хорошо упомянуть single source of truth: экран подписан на Flow из Room, а сеть только обновляет базу.
Где спотыкаются
Пробрасывают DTO прямо в UI. Переименование поля на бэкенде тогда ломает экраны, а nullable-поля сервера расползаются проверками по всему интерфейсу.
Делают методы репозитория синхронными, как fun getUser(id: Int): User, и зовут их из ViewModel. Правильно suspend или Flow, а переключение на Dispatchers.IO скрыто внутри data-слоя.
Держат LiveData в репозитории. Это UI-инструмент с привязкой к жизненному циклу, в data-слое уместнее Flow.