Проектування архітектури мобільного додатка
Неправильно обрана архітектура — це не «технічний борг» у абстрактному сенсі. Це конкретна ситуація через 6 місяців: додати push-сповіщення неможливо без переписування трьох екранів, тому що бізнес-логіка знаходиться прямо в ViewController, а навігація привязана до AppDelegate. Проектування архітектури до початку розробки — це інвестиція, яка окупається при першій значущій зміні вимог.
Вибір шаблону: не MVVM «за умовчанням»
MVVM став стандартом де-факто як для iOS (SwiftUI + Combine), так і для Android (Jetpack Compose + ViewModel), і Flutter (BLoC / Riverpod). Але «встановити MVVM» без розуміння масштабу проекту означає переускладнити малий додаток або недостатньо структурувати великий.
Що насправді впливає на вибір архітектури:
- Команда та її досвід. Якщо команда не працювала з VIPER — не використовувати VIPER. Освоєння шаблону в продакшені коштує більше його переваг.
- Масштаб та модульність. 5 екранів — достатньо простого MVVM без Clean Architecture. 50 екранів з командою 8 осіб — Clean Architecture обов'язкова, інакше конфлікти в спільних файлах і відсутність ізоляції.
- Вимоги до тестованості. VIPER і Clean Architecture дають кращу тестованість через інверсію залежностей, але вимагають дисципліни від всієї команди.
- Платформа. iOS, Android і Flutter мають різні шаблони: VIPER органічна для iOS/UIKit, MVP історично популярна на Android з MVP-бібліотеками, BLoC став стандартом для Flutter.
Що входить у проектування архітектури
Це не схема в Miro з прямокутниками «Model — View — ViewModel». Повнофункціональне архітектурне проектування включає:
Шарова модель (layering). Визначаємо межі між шарами: Presentation / Domain / Data. Документуємо правила: domain-шар не знає про Flutter/UIKit, data-шар не знає про конкретний UI-фреймворк. Dependency Rule — залежності тільки всередину, ніколи назовні.
Модульна структура (modularization). Для великих проектів: розбиття на feature-модулі (auth, profile, payments, feed). На iOS — Swift Package Manager або cocoapods submodules. На Android — Gradle multi-module. На Flutter — Dart packages всередину монорепо. Модульність дає паралельну розробку команди і керовану час збірки.
Стратегія Dependency Injection. Вибір DI-контейнера: iOS — Resolver / Swinject / ручний чистий DI, Android — Hilt (Dagger2 з кодогенерацією), Flutter — GetIt + injectable. Проектуємо граф залежностей, визначаємо часи життя об'єктів (singleton / scoped / transient).
Навігація. iOS: UINavigationController / Coordinator pattern / SwiftUI NavigationStack. Android: Jetpack Navigation Component з NavGraph. Flutter: go_router з deep linking. Координаторний шаблон важливий при складній навігації з умовами (авторизований / не авторизований / onboarding не пройден).
Стратегія управління станом (state management). Не просто «використовуємо Riverpod» — а як саме: де живе глобальний стан (користувач, тема, locale), де локальний (стан конкретного екрана), як обробляються помилки (AsyncValue.error), як розділяються побічні ефекти.
Мережевий шар. Retrofit (Android) / Moya (iOS) / Dio (Flutter). Interceptors для авторизації (token refresh), логування, retry-логіки. Обробка помилок: маппінг HTTP-кодів у доменні помилки, не пробрасування DioException у presentation-шар.
Офлайн-стратегія. Чи вам потрібна офлайн-підтримка взагалі? Якщо так: Room (Android) / Core Data / SwiftData (iOS) / drift або Hive (Flutter). Repository pattern як абстракція над remote + local data sources: спочатку читаємо з кешу, у фоні оновлюємо з мережі.
Документація архітектури
Результат роботи — не тільки робочий scaffold. Документуємо як:
- ADR (Architecture Decision Records) — чому обрали саме цей шаблон, які альтернативи розглядали
- Діаграми компонентів і залежностей (C4 model: Context → Container → Component)
- Coding conventions та приклади для кожного шару
- Шаблонна структура feature-модуля, якої дотримується вся команда
Практичний кейс
У проекті Flutter-додатка для логістики (30+ екранів, реалтайм трекінг, офлайн-робота водія) первісна архітектура була «BLoC везде без чіткого розділення шарів». Через 4 місяці: BLoC напряму викликав Dio, тести не писалися (неможливо ізолювати), додання нової фіче вимагало правок у 5–7 непов'язаних файлах.
Рефакторинг на Clean Architecture з GetIt + injectable, go_router, drift для офлайну зайняв 3 тижні, але наступні 6 місяців команда додавала фічі в 2 рази швидше.
Порівняння підходів
| Критерій | MVC/MVP | MVVM | Clean Architecture |
|---|---|---|---|
| Поріг входу | Низький | Середній | Високий |
| Тестованість | Низька | Середня | Висока |
| Масштаб команди | 1–2 осіб | 2–5 осіб | 5+ осіб |
| Час на проектування | 0.5 дня | 1 день | 3–5 днів |
| Окупність | З першого місяця | З 3-го місяця | З 6-го місяця |
Процес та строки
- Аудит вимог — функціональні та нефункціональні вимоги, NFR по продуктивності і офлайну
- Аналіз платформи та стеку — iOS / Android / Flutter / cross-platform, існуючий код якщо є
- Проектування — вибір шаблонів, документування рішень, ADR
- Реалізація scaffold — базова структура проекту з прикладами для кожного шару
- Код-ревью та онбординг — пояснення команді принципів, code review перших фіч
Проектування архітектури: 3–5 днів. Для legacy-рефакторингу з існуючим кодом — більше. Вартість розраховується після аналізу вимог до масштабування та складу команди.







