У вас в приложении вылез критический баг: на iOS 17.2 сломана авторизация. Исправление в коде готово, но сборка проходит review 2 дня, а App Store — ещё сутки. Dynamic Config отключает проблемный функционал за 10 минут без релиза. Мы внедрили его в 20+ проектах с аудиторией до 10 млн пользователей: от fintech до маркетплейсов. Как показывает практика, сервис конфигурации снижает время реакции на срочные изменения с 3 дней до 10 минут — в 432 раза быстрее. Экономия на горячих фиксах достигает 90%, а затраты на релизный цикл сокращаются на 30%. Например, в проекте с 5 млн пользователей правильная настройка сэкономила значительные средства на экстренных исправлениях.
Remote Config — механизм доставки конфигурационных параметров в мобильное приложение без обновления через App Store или Google Play. Отличие от Feature Toggles: флаги управляют включением/выключением функциональности, а динамическая конфигурация — числовыми, строковыми и JSON-параметрами. Например, Feature Toggle включает новый алгоритм ленты, а Remote Config задаёт количество постов (5, 10, 15) и длину текста. Наш опыт гарантирует, что вы избежите типовых ошибок: превышения квоты Firebase (10 000 запросов/день), неверных дефолтов или утечки конфиденциальных данных.
Remote Config: динамические параметры мобильного приложения — зачем и как?
Remote Config позволяет менять параметры без релиза, что критично для A/B-тестов, срочных исправлений и адаптации под разные рынки. В отличие от Feature Toggles, он работает с любыми типами данных: числа, строки, JSON. Это даёт гибкость: можно менять лимиты API, URL серверов, тексты, цвета и даже целые блоки UI.
Как настроить Firebase Remote Config?
Шаг 1. Подключите SDK — remote config динамические
iOS:
let remoteConfig = RemoteConfig.remoteConfig()
let settings = RemoteConfigSettings()
settings.minimumFetchInterval = isDebug ? 0 : 3600
remoteConfig.configSettings = settings
Android (Kotlin):
val remoteConfig = Firebase.remoteConfig
remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults)
Firebase documentation recommends minimum fetch interval of 3600 seconds for production builds.
Шаг 2. Установите дефолтные значения
Это не опциональная деталь. Если Remote Config недоступен (первый запуск без сети, Firebase outage), приложение работает с дефолтами. Без явно прописанных дефолтов SDK возвращает пустые строки и нули. api_timeout_seconds = 0 — каждый запрос немедленно тайм-аутится. Дефолты в iOS — RemoteConfigDefaults.plist, Android — res/xml/remote_config_defaults.xml. Когда добавляется новый параметр — дефолт добавляется одновременно.
Шаг 3. Fetch + Activate
remoteConfig.fetchAndActivate { status, error in
let timeout = remoteConfig["api_timeout_seconds"].numberValue.intValue
}
remoteConfig.fetchAndActivate().addOnCompleteListener { task ->
val maxRetries = remoteConfig.getLong("max_auth_retries").toInt()
}
Как избежать типичных ошибок при настройке Remote Config?
Дефолты — страховка на случай сбоя сети или ошибки сервера. Храните их в репозитории и обновляйте вместе с кодом. В одном проекте клиент забыл задать дефолт для api_timeout_seconds — после обновления все запросы падали с таймаутом. Исправили за час, но потеряли 15% активных пользователей. 100% проектов с Remote Config должны иметь дефолты для каждого параметра. Ещё одна частая ошибка — превышение квоты Firebase: бесплатный тариф — 10 000 запросов в день. Увеличивайте fetch interval до 12 часов в production, используйте кеш (UserDefaults/SharedPreferences). Для A/B-тестов рассмотрите кастомный сервер или платный план. Экономия от правильной настройки — до 100 000 запросов в месяц (10% от квоты бесплатного плана).
Чек-лист: проверка готовности Remote Config:
- У всех параметров заданы дефолты
- Fetch interval установлен: production ≥ 3600 сек, debug = 0
- Реализован кеш на клиенте
- Условия таргетинга корректны (версия, страна, процент)
- Проведено нагрузочное тестирование (симуляция offline)
- Документация по добавлению новых параметров
Условные значения (Conditions)
Remote Config поддерживает targeting по: версии приложения, стране/региону, языку устройства, случайному проценту пользователей. Это позволяет:
- Включить новый CDN-эндпоинт только для европейских пользователей
- Показать особую конфигурацию пользователям бета-версии (app version contains "beta")
- Постепенно переключить 10% пользователей на новый алгоритм ленты
Сравнение Firebase Remote Config и собственного сервиса
| Критерий |
Firebase Remote Config |
Кастомный Config‑сервис |
| Время запуска |
1–2 дня |
2–3 недели |
| Стоимость |
Бесплатно (10k запросов/день) |
Индивидуально |
| Таргетинг |
По версии, стране, языку, проценту |
Любые условия (IAM, корп. данные) |
| Конфиденциальность |
Данные уходят в Google |
Полный контроль |
| Admin UI |
Firebase Console |
Свой интерфейс |
| Кеш клиента |
UserDefaults / SharedPreferences |
UserDefaults / SharedPreferences |
Remote Config vs Feature Toggles: в чём разница?
| Критерий |
Remote Config |
Feature Toggles |
| Тип данных |
Числа, строки, JSON |
Булево (вкл/выкл) |
| Пример |
max_items=100, api_url="..." |
new_checkout_enabled=true |
| Условия |
Версия, страна, язык, % пользователей |
То же |
| Частота изменений |
Низкая (кешируется) |
Высокая (может меняться мгновенно) |
| Применение |
Настройка параметров |
Включение/выключение функционала |
На практике их комбинируют: Feature Toggles включает новый модуль, Remote Config задаёт его конфигурацию.
Когда нужен собственный Remote Config сервис?
Firebase не всегда подходит: нельзя отправлять данные пользователей в Google, нужны кастомные условия таргетинга, или требуется интеграция с корпоративной IAM-системой. Минимальная архитектура включает API endpoint GET /api/config?appVersion=X&platform=ios®ion=eu, Redis для кеша, PostgreSQL для хранения параметров, и Webhook для мгновенной инвалидации. Admin UI позволяет нетехническим сотрудникам менять значения. Свяжитесь с нами для оценки — подберём оптимальное решение под вашу инфраструктуру.
Что входит в работу по интеграции Remote Config
- Аудит текущих параметров и выбор стратегии (Firebase / custom)
- Настройка SDK, дефолтов, условий таргетинга
- Разработка API (при custom) и админ-панели
- Деплой, мониторинг, обучение команды
- Документация по добавлению новых параметров
- Гарантия 3 месяца на корректную работу конфигурации
Получите индивидуальный план внедрения Remote Config с учётом специфики вашего приложения. Закажите консультацию — мы проанализируем текущую конфигурацию и предложим оптимальное решение. Оставьте заявку — мы свяжемся с вами в течение 24 часов и обсудим детали.
Архитектура мобильных приложений
Приложение собрано в одном ViewController на 2000 строк. Сетевые вызовы, бизнес-логика, обновление UI — всё в одном месте. Добавить новую фичу без регрессии сложно, написать тест невозможно. Это не «плохой код» — это отсутствие архитектуры. И это встречается чаще, чем можно ожидать, даже в production-приложениях с миллионом пользователей.
Мы проектируем архитектуру под ключ: от выбора паттерна до полной структуры проекта с тестами и документацией. За 7–10 дней получаете чистый модульный код, готовый к масштабированию.
Архитектурные паттерны в мобайле решают одну задачу: отделить UI от логики так, чтобы каждая часть была тестируемой и заменяемой.
MVVM: базовый паттерн
Model-View-ViewModel — стандарт для iOS (SwiftUI + Combine/async, UIKit + Combine) и Android (Jetpack ViewModel + StateFlow + Compose). ViewModel содержит состояние UI и бизнес-логику. View только отображает состояние и передаёт намерения пользователя в ViewModel. Model — данные и их источник.
Ключевое правило: ViewModel не знает об UIKit или Android View-классах. Нет импортов UIKit, нет Context-зависимостей (кроме Application context через Hilt). Это гарантирует тестируемость: ViewModel тестируется как чистый Kotlin/Swift-код без Android Instrumented Test.
MVVM закрывает 70% потребностей. Остальные 30% — где нужна строгая изоляция фич, масштабирование команды, сложный flow управления состоянием.
Clean Architecture: когда MVVM недостаточно
Добавляет слои поверх MVVM:
Domain-слой — бизнес-логика, независимая от платформы. UseCase (или Interactor) содержит одно бизнес-правило: GetUserOrdersUseCase, PlaceOrderUseCase. Зависит только от интерфейсов (protocol/interface), не от конкретных реализаций.
Data-слой — реализация репозиториев. OrderRepositoryImpl реализует OrderRepository из domain. Знает про Retrofit, Room, UserDefaults. ViewModel не знает, откуда данные — из сети или кеша.
Presentation-слой — ViewModel + View. Знает о Domain, не знает о Data.
Dependency rule: зависимости направлены только внутрь. Domain не зависит ни от чего. Data и Presentation зависят от Domain.
Presentation → Domain ← Data
Это даёт возможность подменять реализацию: тест использует in-memory репозиторий вместо сетевого, интерфейс остаётся тем же.
Практическая оговорка: Clean Architecture добавляет файлы и слои. Для небольшого приложения это overhead. Оправдан от ~15 фич и при команде 3+ разработчиков.
BLoC для Flutter: предсказуемый поток состояний
BLoC (Business Logic Component) — стандартный паттерн в Flutter-сообществе. Библиотека flutter_bloc реализует его через два типа: Bloc (Event → State) и Cubit (State без Events, только методы).
Bloc обрабатывает Event и эмитирует новый State через on<EventType> хендлеры. Состояние иммутабельно — новый объект на каждое изменение. BlocBuilder перерисовывает только ту часть дерева, где изменился state.
// Event
abstract class CartEvent {}
class AddItemToCart extends CartEvent {
final String productId;
AddItemToCart(this.productId);
}
// State
abstract class CartState {}
class CartLoaded extends CartState {
final List<CartItem> items;
CartLoaded(this.items);
}
// Bloc
class CartBloc extends Bloc<CartEvent, CartState> {
CartBloc(this._cartRepository) : super(CartLoaded([])) {
on<AddItemToCart>(_onAddItem);
}
Future<void> _onAddItem(AddItemToCart event, Emitter<CartState> emit) async {
final current = state as CartLoaded;
final updated = await _cartRepository.addItem(event.productId);
emit(CartLoaded(updated));
}
}
Преимущество BLoC — тестируемость. blocTest из bloc_test пакета позволяет проверить: при таком-то Event, с таким-то начальным State, BLoC должен эмитировать такой-то State. Без UI, без моков для Flutter-фреймворка.
VIPER: для крупных iOS-проектов
VIPER (View, Interactor, Presenter, Entity, Router) — наиболее строгое разделение обязанностей для iOS. Каждый компонент имеет протокол и конкретную реализацию.
-
View — только UI, делегирует всё Presenter
-
Interactor — бизнес-логика, работа с сетью и данными
-
Presenter — посредник между View и Interactor, форматирует данные для View
-
Entity — модели данных (чистые структуры)
-
Router — навигация между модулями
Каждый модуль (экран или фича) — отдельный VIPER-модуль. Это исключает coupling между фичами и позволяет большим командам работать параллельно без конфликтов.
Цена: много файлов, много протоколов. Шаблонный код генерируется через Sourcery или кастомные Xcode-шаблоны. VIPER оправдан для приложений с 10+ разработчиками и 50+ экранами.
TCA (The Composable Architecture)
TCA от Point-Free — более современная альтернатива VIPER для iOS/macOS. Основные концепции: State (иммутабельное состояние фичи), Action (все возможные события), Reducer (State + Action → новый State + Effect), Store (хранит State, обрабатывает Actions).
Scope позволяет composable строить большие фичи из маленьких: родительский Reducer делегирует часть State дочернему. Каждая фича тестируется изолированно через TestStore с точным контролем над Effects.
TCA имеет крутую кривую обучения, но даёт предсказуемость, которую сложно получить другим способом: каждое изменение состояния — явный Action с конкретным источником.
Какой паттерн выбрать под вашу задачу?
Оценим проект за 1 день — подберём архитектуру с учётом размера команды, платформы и планов роста.
| Паттерн |
Платформа |
Команда |
Когда выбирать |
| MVVM |
iOS, Android, Flutter |
1–5 |
Стартовый стандарт, MVP, небольшие проекты |
| MVVM + Clean |
iOS, Android |
3–10 |
Средние проекты, тестируемость критична |
| BLoC |
Flutter |
2–8 |
Flutter с предсказуемым state management |
| VIPER |
iOS |
5–20 |
Крупные iOS-проекты, модульная архитектура |
| TCA |
iOS/macOS |
3–15 |
Строгая тестируемость, Swift Concurrency |
Универсального ответа нет. Архитектуру выбирают под размер команды, требования к тестируемости и горизонт поддержки приложения.
Что входит в нашу работу
-
Аудит текущей архитектуры (если приложение уже существует) — выявим узкие места и регрессионные зоны.
-
Проектирование модульной структуры с чёткими границами слоёв и правилами зависимостей.
-
Создание каркаса проекта (Scaffold) с внедрением DI, организации папок и настройки линтеров.
-
Написание юнит-тестов для слоя домена и ViewModel — минимум 80% покрытия ключевых use case.
-
Подготовка документации — архитектурные диаграммы, README с правилами модификации кода, инструкция для онбординга новых разработчиков.
-
Передача рабочего репозитория с CI-пайплайном (GitHub Actions / Bitrise), настроенным запуском тестов и статическим анализом.
Всё это входит в стоимость проектирования. Дополнительно — поддержка на этапе внедрения: консультации команды, code review первых pull request.
Что происходит без архитектуры
Типичный сценарий через 18 месяцев без архитектуры: 40% времени разработки уходит на дебаг регрессий. Новый разработчик разбирается в коде неделю перед тем, как сделать первый PR. Тесты не пишутся, «потому что сложно мокировать». Добавление новой фичи требует понимания половины кодовой базы.
Выбор архитектуры на старте — это инвестиция с возвратом через 3–6 месяцев. По нашим данным, правильно спроектированная архитектура с MVVM + Clean даёт в 3 раза меньше регрессий по сравнению с монолитным ViewController. А затраты на её внедрение окупаются за 2–3 спринта.
Согласно рекомендациям Apple по проектированию приложений, разделение ответственности — ключевой фактор устойчивости кода (https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaViewController.html).
Почему стоит доверить архитектуру профессионалам?
Неправильный выбор паттерна на старте ведёт к переписыванию половины кода через год. Мы видели десятки проектов, где попытка сэкономить на архитектуре оборачивалась многомесячным рефакторингом. У нас за плечами 10+ лет коммерческой разработки, опыт работы с приложениями от 1 до 50 разработчиков. Мы помогаем избежать типовых ошибок:
- Overengineering для простого MVP (назначаем MVVM, а не VIPER).
- Отсутствие dependency injection — подключаем Hilt/Koin/Dagger уже на старте.
- Игнорирование тестируемости — закладываем протоколы/интерфейсы с первого коммита.
Оценим ваш проект бесплатно — пришлите описание текущего приложения или идеи, и мы подберём оптимальную архитектуру за 1 день. Пишите в Telegram или на почту — в ответ вы получите архитектурную схему, план внедрения и смету.
Дополнительная таблица: сравнение затрат на внедрение
| Паттерн |
Время проектирования |
Количество файлов на 1 экран |
Время написания тестов |
| MVVM |
2–3 дня |
5–7 |
1 день |
| MVVM + Clean |
4–5 дней |
10–12 |
2 дня |
| BLoC |
3–4 дня |
6–8 |
1.5 дня |
| VIPER |
5–7 дней |
12–15 |
2.5 дня |
| TCA |
5–6 дней |
8–10 |
2 дня |
Время указано для команды из 2–3 разработчиков. С нашим шаблоном (generator) стартовый каркас готов за 1 день вне зависимости от выбранного паттерна.