Архитектура Суперапп на Android: Правила выживания

Суперапп — это не просто большое приложение. Это экосистема, где мессенджер, соцсеть, музыка и видео живут под одной крышей. И главная боль здесь не время компиляции. Боль — это хаос в коммуникации между сервисами, костыли и архитектурный долг, который копится с каждым спринтом.

Когда команд пять, а модулей — пятьдесят, без строгих правил проект превращается в карточный домик. Вот некоторые правила, которые я вывел на практике.

Правило 1: Data-слой живёт с фичей

Глобальный модуль данных — это ловушка. Репозиторий чатов и репозиторий аудиоплеера не имеют ничего общего. У них разная логика кэширования, частота инвалидации, модели ошибок. Каждый сервис получает свой data-слой внутри собственного модуля реализации. Это даёт полную инкапсуляцию: изменения схемы базы данных в мессенджере не затрагивают плеер.

Правило 2: UI — отдельный модуль

Оставлять UI-компоненты в фича-модулях для супераппа — путь к визуальному хаосу. Когда кнопка в мессенджере отличается от кнопки в плеере, страдает пользовательский опыт. Дизайн-система живёт в отдельном модуле, независимом от бизнес-логики. Это позволяет менять визуальный язык приложения централизованно.

Правило 3: Коммуникация только через API-контракты

Настоящая боль — когда разработчики связывают модули костыльно: прямыми импортами, магическими строками в Intent или шиной событий без контрактов. Жёсткое правило: модули не знают о существовании друг друга, только об интерфейсах. Каждый сервис публикует модуль с публичным API, а реализация скрыта. Другие сервисы зависят исключительно от контрактов.

Правило 4: Навигация — отдельный модуль

Прятать навигацию в модуль приложения — ошибка. Фича-модули до неё просто не достучатся. Навигация между сервисами выделяется в самостоятельный модуль. В нём живут интерфейсы навигаторов, общие маршруты и реализации роутеров. Модуль приложения только инициализирует навигацию, но не владеет её контрактами.

Правило 5: DI живёт внутри фичи

Не нужно выносить конфигурацию внедрения зависимостей в отдельные Gradle-модули. Достаточно организовать структуру пакетов внутри каждой фичи: data, domain, ui и di. Модуль приложения импортирует все фичи и собирает граф зависимостей на верхнем уровне. При этом сам DI-код остаётся рядом с кодом, который он конфигурирует.

Правило 6: Изоляция через навигационные интерфейсы

Прямой вызов Activity из одного модуля в другой нарушает изоляцию. Вместо этого используются навигационные интерфейсы, опубликованные в модуле навигации. Реализация живёт в модуле сервиса, а интерфейс доступен всем. Любой сервис может инициировать переход, не зная ничего о внутреннем устройстве целевого экрана.

Сухой остаток

Эти правила не про красивый код. Они про выживание продукта с пятью командами и сотнями тысяч строк. Когда каждый сервис изолирован, а коммуникация идёт строго по контрактам — архитектура выдерживает рост и не превращается в монолит, который страшно трогать.

А с какими архитектурными вызовами сталкивались вы при построении крупных приложений?

Архитектура Суперапп на Android: Правила выживания | Сетка — социальная сеть от hh.ru