Какие правила зависимости слоев и как должны быть связаны модули приложения
Что проверяют
Понимаете ли вы, куда направлены зависимости между слоями и модулями и чем это подкреплено в сборке, а не только на схеме. Следом спрашивают, как связать два фича-модуля и где живут интерфейсы репозиториев.
Как отвечать
Опирайтесь на рекомендованную архитектуру Android:
- UI-слой: Compose или View плюс
ViewModel. Отдаёт состояние черезStateFlow, принимает события, данные текут в одну сторону; - domain-слой (необязателен): use case с бизнес-логикой, которую переиспользуют несколько экранов. Лучше делать его чистым Kotlin-модулем без Android SDK;
- data-слой: репозитории и источники данных, Room, Retrofit, DataStore.
Стрелки идут от UI к данным, обратно никогда. В варианте Clean Architecture domain не зависит ни от кого: интерфейс UserRepository объявлен в domain, реализация лежит в data, а связывает их DI (Hilt или Koin). Это и есть инверсия зависимостей: data зависит от domain, а не наоборот.
Типовая схема модулей, как в образце Now in Android:
:app: собирает всё и отвечает за навигацию верхнего уровня;- *`:feature:
**: фичи не зависят друг от друга. Переход между ними идёт через навигацию в:appили через отдельныйapi-модуль фичи с публичным контрактом, а реализация лежит вimpl`; - *`:core:`**: общие данные, сеть, дизайн-система, от них зависят фичи.
В Gradle подключайте модули через implementation, а не api: транзитивные зависимости не утекают наружу, и при изменении модуля пересобирается меньше. Общую конфигурацию выносят в convention-плагины в build-logic, а правила зависимостей проверяют автоматически, например тестами на Konsist.
Где спотыкаются
Тащат в domain сущности Room или DTO из Retrofit. После этого слой уже не чистый, и смена источника данных ломает бизнес-логику.
Связывают фича-модули напрямую ради одного перехода между экранами. Через полгода граф зависимостей превращается в клубок, и сборка перестаёт распараллеливаться.
Держат в ViewModel ссылку на Activity или её Context. Это утечка памяти при повороте экрана и признак того, что логика оказалась не в своём слое.