Яндекс.Метрика
Услуги Портфолио Контакты БлогНовости +7 (800) 511‑32‑27 Обсудить проект
Mobile

Архитектура мобильного приложения: слои, компоненты и паттерны

13 августа 2026·11 мин чтения
Юрий Пухов
Автор материалаЮрий ПуховCEO, YuSMP Group
Профиль автора
Слои архитектуры мобильного приложения

По данным Statista, совокупно в Google Play и App Store представлено более 4,5 миллиона приложений — и конкуренция за место в топе только ужесточается. При этом многие проекты проигрывают не из-за плохих идей, а из-за скрытой причины — неудачной архитектуры мобильного приложения. Когда кодовая база превращается в запутанный монолит, каждый новый экран или фича обходится вдвое дороже, а обновления превращаются в минное поле. Именно поэтому Google в своём Guide to App Architecture и Apple в официальной документации закрепили архитектурные рекомендации на уровне платформенного стандарта: слои, однонаправленный поток данных и разделение ответственности закладываются до первой строки кода.

В этой статье я разберу архитектуру мобильного приложения по слоям и паттернам — без академического тумана, с фокусом на то, как это влияет на скорость выпуска фич, стоимость поддержки и устойчивость продукта к изменениям. Материал будет полезен продакт-менеджерам, CTO и предпринимателям, которые хотят говорить с разработчиками на одном языке и принимать обоснованные решения.

Содержание

Что такое архитектура мобильного приложения и зачем она нужна

Архитектура ≠ технологический стек: разделяем понятия

Когда я слышу вопрос «а на каком стеке у вас написано?», за ним нередко скрывается другой, более важный: «а как у вас внутри всё устроено?». Стек — это Kotlin, Swift или Flutter, Jetpack Compose или SwiftUI. Архитектура — это принципы организации кода: как разделены слои ответственности, как данные движутся между компонентами, как части системы общаются. Можно взять один и тот же Kotlin и реализовать на нём как чистое MVVM, так и то, что принято называть «архитектурой-спагетти».

Архитектура определяет три вещи, которые напрямую влияют на бизнес-показатели продукта:

  • Скорость выпуска фич. Когда логика размазана по всем слоям, добавить новый экран — значит переписать половину приложения. В хорошо структурированном коде экраны добавляются независимо.
  • Стоимость сопровождения. По нашему опыту, поддержка приложения без явной архитектуры обходится в 2–3 раза дороже: больше багов при каждом изменении, дольше онбординг новых разработчиков.
  • Технический долг. Отсутствие архитектурных принципов — это кредит, который рано или поздно придётся отдавать переработками или полным переписыванием продукта.

Что даёт продуманная архитектура бизнесу

Представьте два сценария. В первом — разработчик меняет источник данных с REST на GraphQL. При правильной архитектуре он трогает только data-слой: правит репозиторий, тесты проходят, PR закрыт за день. Во втором сценарии логика запросов разбросана по фрагментам и ViewModel-ах — изменения расползаются по десяткам файлов, и любая доработка несёт риск регрессии. Хорошая архитектура делает второй сценарий невозможным.

Слои архитектуры: presentation, domain, data

Современная рекомендация Google и де-факто стандарт в мобильной разработке — трёхслойная модель: Presentation → Domain → Data. Каждый слой знает только о слое ниже, но не знает о слое выше. Это и есть принцип разделения ответственности (separation of concerns).

Слой Ответственность Примеры компонентов
Presentation (UI) Отображение состояния, обработка ввода пользователя Activity, Fragment, Composable (Android); View, UIViewController, SwiftUI View (iOS); ViewModel, UiState
Domain (бизнес-логика) Бизнес-правила, use cases, доменные модели UseCase / Interactor, доменные Entity, валидация, агрегация данных
Data Получение и хранение данных, абстракция источников Repository, DataSource (Remote/Local), Room / Core Data, Retrofit / URLSession

Presentation (UI) — экраны, состояние, взаимодействие с пользователем

Задача UI-слоя — отобразить состояние и отдать пользовательские события вниз. Presentation-слой ничего не знает о том, откуда пришли данные: для него существует только ViewModel (или иной «посредник»), который поставляет готовый UiState. Это позволяет тестировать логику отображения отдельно от бизнес-правил и сетевого слоя.

Domain — бизнес-логика, use cases, независимость от фреймворков

Domain-слой — сердце приложения и единственный по-настоящему платформенно-независимый слой. Здесь живут use cases: «получить список заказов», «рассчитать корзину», «авторизовать пользователя». Use case берёт данные из репозитория, применяет бизнес-правила и возвращает результат в ViewModel. Если domain-слой написан без зависимостей от Android SDK или UIKit, его можно переиспользовать между нативным и кросс-платформенным приложением — или покрыть тестами без эмулятора.

Data — репозитории, источники данных, локальная БД и сеть

Data-слой инкапсулирует всю логику получения и хранения данных. Центральная абстракция — репозиторий: он принимает запрос от domain-слоя и сам решает, откуда брать данные — из кэша (Room/SQLite, Core Data), из сети (REST/GraphQL API) или из локального файла. Это позволяет менять источник данных, не затрагивая бизнес-логику и UI.

Принцип separation of concerns и однонаправленный поток данных (UDF)

Однонаправленный поток данных (Unidirectional Data Flow) означает: данные движутся сверху вниз (от ViewModel к UI), а события — снизу вверх (от UI к ViewModel). Никаких «обратных связей» через колбэки или прямых ссылок между экранами. Этот принцип заложен в основу Jetpack Compose, SwiftUI и всех современных мобильных архитектур. Благодаря UDF состояние приложения всегда предсказуемо и воспроизводимо — это упрощает отладку и тестирование.

Архитектурные паттерны: MVC, MVP, MVVM, MVI, Clean Architecture

MVC и MVP — классика и её ограничения на мобильных

MVC (Model-View-Controller) — исторически первый паттерн на мобильных, тесно связанный с UIKit и ранним Android. Его главная проблема: Controller (Activity/ViewController) быстро разрастается до «God Object», берёт на себя и навигацию, и бизнес-логику, и работу с данными — так появился знаменитый «Massive ViewController».

MVP (Model-View-Presenter) вынес логику в Presenter, отделив её от View. Это улучшило тестируемость, но породило другую проблему: жёсткую связку View и Presenter через интерфейсы. При изменении требований к UI интерфейс приходилось менять синхронно с Presenter, что увеличивало объём рутинного кода.

MVVM — доминирующий паттерн

MVVM (Model-View-ViewModel) сегодня — стандарт де-факто для Android (Jetpack ViewModel + StateFlow / LiveData) и iOS (SwiftUI + Observation framework / Combine). ViewModel хранит и преобразует состояние UI, не имея прямой ссылки на View. Связь между ними — через реактивный поток данных: View подписывается на UiState и обновляется автоматически при изменении состояния. Это даёт низкий порог входа, хорошую тестируемость ViewModel и естественную интеграцию с платформенными инструментами.

MVI и однонаправленный state

MVI (Model-View-Intent) развивает идеи MVVM дальше: весь UI-слой описывается как цикл Intent → State → View. Пользовательское действие создаёт Intent, он обрабатывается через Reducer, который меняет неизменяемое (immutable) состояние — и View рендерит новое состояние. MVI отлично масштабируется на сложный UI со многими источниками событий: помогает избежать состояний-гонки и делает поток событий аудируемым. На Android это реализуется через библиотеки вроде Orbit MVI или собственный Kotlin Flow + sealed class.

Clean Architecture / VIPER — когда оправдана дополнительная сложность

Clean Architecture по Роберту Мартину вводит явную зависимость только «внутрь»: presentation зависит от domain, domain — ни от чего. На iOS этот принцип реализуется через VIPER (View-Interactor-Presenter-Entity-Router). Добавляются явные границы через протоколы и инверсию зависимостей. Цена — значительный boilerplate и высокий порог входа. Оправдана в крупных приложениях с несколькими командами: четкие границы модулей позволяют командам работать параллельно без конфликтов.

Сравнительная таблица паттернов

Паттерн Суть Тестируемость Сложность / порог входа Когда применять
MVC Контроллер управляет логикой и UI Низкая (логика в контроллере) Низкая Прототипы, очень маленькие приложения
MVP Presenter отделён от View через интерфейс Средняя Средняя Небольшие Android-приложения без Jetpack
MVVM ViewModel хранит состояние; View реагирует на поток Высокая Низкая — средняя Большинство новых проектов, рекомендован Google и Apple
MVI Циклическая модель Intent → State → View Очень высокая Средняя — высокая Сложный UI, много источников событий, строгий аудит состояний
Clean / VIPER Строгие слоевые границы, инверсия зависимостей Очень высокая Высокая Большие команды, долгий жизненный цикл, сложная бизнес-логика

Сквозные компоненты архитектуры

Управление состоянием (state management)

Состояние — это то, что UI отображает в данный момент. Управлять им сложно: состояние может прийти с сервера, из базы данных, от пользователя или из нескольких мест одновременно. Современный подход — хранить единое неизменяемое UiState в ViewModel и обновлять его атомарно. На Android это StateFlow / MutableStateFlow; на iOS — @Observable (Observation framework в Swift 5.9+) или @Published + ObservableObject. Это исключает ситуации, когда разные части UI имеют несогласованное состояние.

Навигация

Навигация — точка сбора всех экранов приложения, и она часто становится узким местом архитектуры. Ошибка — держать логику навигации в Activity или Fragment. Правильный подход — выделить навигацию в отдельный компонент: NavController в Jetpack Navigation (Android) или NavigationStack в SwiftUI. В Clean Architecture / VIPER навигацию выносят в Router — отдельный объект, который обновляется ViewModel-ом через события.

Внедрение зависимостей (DI)

Без DI каждый компонент сам создаёт свои зависимости — это связывает код, делает его нетестируемым и усложняет подмену реализаций. Стандарт на Android — Hilt (обёртка над Dagger 2), которая интегрирована в Jetpack и покрывает жизненные циклы компонентов. На iOS используют Resolver, Swinject или ручной dependency container. Правильный DI позволяет в тестах передавать mock-зависимости, не меняя код продакшн-компонентов.

Работа с данными: offline-first, кэш, синхронизация

Пользователи ожидают, что приложение работает при плохом соединении или его отсутствии. Паттерн offline-first означает: источником истины для UI всегда является локальная база данных (Room / SQLite на Android, Core Data или GRDB на iOS). Репозиторий по запросу возвращает кэш немедленно, параллельно обновляя его из сети. Стратегии: cache-first (сначала кэш, потом сеть), network-first (сначала сеть, при сбое — кэш), stale-while-revalidate (кэш немедленно + тихое обновление). Для синхронизации фоновых изменений на Android используют WorkManager; на iOS — BGAppRefreshTask и URLSession background transfers.

Безопасность: хранение секретов, шифрование, авторизация

Безопасность в архитектуре — это не отдельная фича, а сквозное требование. Три ключевых принципа: никогда не хранить токены и чувствительные данные в SharedPreferences или UserDefaults в открытом виде — только в Android Keystore / iOS Keychain; шифровать локальную базу данных (SQLCipher для Room); авторизационные токены передавать исключительно через HTTPS, а логику обмена токенами изолировать в data-слое. Взаимодействие с бэкендом — это тоже часть data-слоя: разработка API должна проектироваться совместно с клиентским data-слоем, чтобы авторизация, версионирование и обработка ошибок были согласованы.

Архитектура и способ разработки: нативная vs кросс-платформа

Нативная разработка (Kotlin/Jetpack, Swift/SwiftUI)

Нативная разработка даёт полный доступ к платформенным API и максимальную производительность. На Android архитектурный стандарт — Jetpack: ViewModel, Room, Navigation, WorkManager. Google рекомендует MVVM с однонаправленным потоком и Jetpack Compose как UI-фреймворк. На iOS Apple движется к SwiftUI + Observation + Swift Concurrency (async/await) как современному стеку. Каждая платформа диктует свои паттерны, но принципы слоёв остаются едиными.

Flutter / React Native — как ложатся те же слои и паттерны

Кросс-платформенные фреймворки не отменяют необходимость архитектуры — они лишь меняют инструменты. В Flutter широко применяют BLoC (Business Logic Component) — аналог MVI — или Riverpod как state management. React Native использует Zustand, Redux Toolkit или MobX. Принципиальное преимущество кросс-платформы — единый domain-слой: бизнес-логика и use cases пишутся один раз и работают и на iOS, и на Android. Data-слой также может быть общим, хотя платформо-специфичные вещи (Keychain vs Keystore, уведомления) всё равно реализуются отдельно.

Влияние выбора на архитектуру data-слоя и переиспользование кода

При нативной разработке две команды (iOS и Android) реализуют репозитории независимо — дублирование логики неизбежно. При кросс-платформенном подходе domain и data-слои общие, что снижает риск расхождения поведения между платформами. Компромисс: нативные интеграции (камера, биометрия, push-уведомления) требуют platform-channel или native-module — здесь дублирования не избежать в любом случае.

Как выбрать архитектуру под свой проект

MVP и небольшие приложения: не переусложнять

Для приложений с 5–10 экранами, простым сценарием и командой из 1–2 разработчиков достаточно MVVM без domain-слоя: ViewModel напрямую вызывает репозиторий. Добавлять use cases, Router и DI-фреймворк на старте — значит тратить время на инфраструктуру вместо продукта. Архитектуру всегда можно усложнить потом — главное заложить правильные границы с первого дня.

Продукты со сложной логикой и долгим жизненным циклом: Clean Architecture

Если приложение — ключевой канал бизнеса, работает несколько лет и развивается несколькими командами, инвестиция в Clean Architecture окупается. Явные границы модулей позволяют командам работать параллельно, снижают время онбординга и делают код аудируемым. Для таких проектов рекомендую сразу закладывать multi-module architecture (Android) или Swift Package Manager modules (iOS) — это принудительно соблюдает границы слоёв на уровне компилятора.

Чек-лист принятия решения

  • Масштаб: сколько экранов, сколько источников данных, насколько сложна бизнес-логика?
  • Команда: сколько разработчиков, каков их опыт с конкретными паттернами?
  • Срок жизни: это MVP на 6 месяцев или продукт на 5 лет?
  • Тестируемость: насколько критичны автоматические тесты для вашего процесса?
  • Темп изменений: как часто будут меняться требования к UI и бизнес-правилам?

Если вы строите мобильный продукт впервые или переосмысливаете архитектуру существующего — наша команда занимается разработкой мобильных приложений под ключ и всегда начинает с аудита требований и выбора архитектурного подхода под задачу.

Частые ошибки в архитектуре мобильного приложения

За годы работы с мобильными проектами я вижу одни и те же паттерны ошибок, которые потом приходится дорого исправлять:

  • Bulky ViewModel / God Object. ViewModel начинает тянуть на себя навигацию, форматирование строк, прямые запросы в БД. Итог — монолитный класс на 2000 строк, который невозможно тестировать.
  • Логика в UI. Бизнес-правила в Activity/Fragment или Composable — классика, которая убивает тестируемость. Любая логика, которую можно протестировать без запуска устройства, должна жить не в UI-слое.
  • Отсутствие слоёв. «Один большой класс, который делает всё» — Data Manager, App Controller. Когда нужно поменять источник данных, перекраивается весь код.
  • Преждевременная оптимизация. Закладывать микросервисную архитектуру в MVP с 500 пользователями — выброшенные деньги. Оптимизируйте то, что измерили как узкое место.
  • Жёсткая связанность с библиотекой. Когда весь код напрямую зависит от конкретного сетевого клиента или ORM — замена библиотеки становится рефакторингом всего приложения. Репозиторий с интерфейсом — страховка от смены инструментов.
  • Отсутствие тестируемости как критерия. «Мы напишем тесты потом» — это технический долг, который растёт быстрее, чем кажется. Хорошая архитектура делает тесты дешёвыми; плохая — делает их невозможными.

Часто задаваемые вопросы

Чем архитектура мобильного приложения отличается от технологического стека?

Технологический стек — это набор языков, фреймворков и инструментов. Архитектура — это структура и принципы организации кода: как разделены слои, как данные движутся между ними, как компоненты общаются. Можно использовать один стек (Kotlin + Jetpack), но реализовывать разные архитектуры — MVVM или MVI.

Какой архитектурный паттерн выбрать для стартапа или MVP?

Для MVP и небольших приложений оптимален MVVM: он широко поддерживается Google (Jetpack ViewModel) и Apple (SwiftUI + Observation), имеет низкий порог входа и достаточную тестируемость. Добавлять Clean Architecture или MVI на старте не стоит — лишние слои абстракции замедлят разработку без реальной пользы при маленькой кодовой базе.

Нужна ли Clean Architecture маленькому приложению?

Нет. Clean Architecture оправдана при сложной бизнес-логике, большой команде и длинном жизненном цикле продукта. Для приложения с 5–10 экранами и простыми сценариями она создаёт избыточную сложность и увеличивает время разработки без видимой пользы.

Отличается ли архитектура для нативной разработки и Flutter или React Native?

Принципы слоёв и паттернов одинаковы — presentation/domain/data, MVVM или MVI работают везде. Разница в инструментах: нативная Android использует Jetpack ViewModel и Coroutines, Flutter — BLoC или Riverpod, React Native — Redux или Zustand. Кросс-платформа даёт единый domain-слой, но UI-слой всё равно платформенный.

Как архитектура влияет на стоимость поддержки приложения?

Продуманная архитектура снижает стоимость поддержки: изолированные модули проще менять без риска регрессий, тестируемый код снижает число багов в проде, а чёткое разделение слоёв позволяет подключить нового разработчика быстро. Монолитная архитектура экономит время в начале, но кратно увеличивает расходы на каждую следующую доработку.

Заключение

Архитектура мобильного приложения — это не академическая теория, а инструмент управления стоимостью разработки и скоростью релизов. Правильно выбранные слои и паттерны превращают каждую новую фичу в предсказуемую задачу с понятной трудоёмкостью. Неправильная архитектура превращает любое изменение в рулетку.

Для большинства новых проектов хорошей отправной точкой будет MVVM с трёхслойной моделью presentation/domain/data — это золотая середина между простотой и масштабируемостью. По мере роста продукта и команды архитектуру можно эволюционно усложнять, не переписывая с нуля. Если вы строите мобильный продукт и хотите заложить правильный фундамент с первого дня — мы в YuSMP Group занимаемся разработкой мобильных приложений под ключ: от выбора архитектуры до выпуска в сторы.

Нужно мобильное приложение?

Спроектируем и разработаем приложение под iOS и Android под вашу задачу.

Обсудить приложение