This page is part of the ForgeSDLC knowledge base — an AI-assisted, human-directed methodology for taking product work from concept to production. For the core operating model and vocabulary, see Forge SDLC overview and What is ForgeSDLC?.
Mobile application architecture (blueprint)
Purpose: Project-agnostic patterns for structuring mobile codebases — separation of concerns, data flow, navigation, dependency injection, modularization, and testing. Use this when choosing or evolving an architecture before codifying decisions in ADRs.
Mobile apps benefit from architectures that isolate UI from domain rules and data access. Constraints differ from server or web front ends: tight main-thread budgets, process death, configuration changes, and platform-specific UI lifecycles. Good architectures trade testability and team scalability against complexity — not every app needs VIPER or full Clean Architecture.
Architecture pattern comparison
Pattern
Layers / roles
Data flow
Testability
Complexity
MVC
Model, View, Controller
View ↔ Controller → Model; often bidirectional
Low–medium (Controller tends to grow)
Low
MVP
Model, View, Presenter
View → Presenter → Model; Presenter updates View via interface
Unidirectional: Intent → reduce → new State → View
High (pure reducers)
Medium–high
VIPER
View, Interactor, Presenter, Entity, Router
Strict boundaries; router owns navigation
High (small types)
High
Clean Architecture
Presentation, Domain, Data
Inward dependencies; use cases orchestrate
High (domain isolated)
High
TCA (The Composable Architecture)
State, Action, Reducer, Environment, Effects
Unidirectional; composable reducers (Swift)
High
Medium–high
MVVM data flow
flowchart LR
subgraph presentation["Presentation"]
V[View / UI]
VM[ViewModel]
end
M[Model / Domain entities]
R[Repository]
DS[(Data sources: API, DB, cache)]
V <-->|observe / commands| VM
VM --> M
VM --> R
R --> DS
Clean Architecture: layers and dependency rule
Dependencies point inward: outer layers depend on inner abstractions, never the reverse.
flowchart TB
subgraph outer["Presentation (UI, ViewModels, coordinators)"]
P[Presentation]
end
subgraph mid["Domain (entities, use cases)"]
D[Domain]
end
subgraph inner["Data (repositories impl, DTOs, APIs, DB)"]
DA[Data]
end
P -->|"depends on interfaces"| D
DA -->|"implements interfaces"| D
Navigation patterns
Pattern
Description
iOS
Android
Stack
Hierarchical push/pop
UINavigationController, SwiftUI NavigationStack
Fragment/Compose back stack, NavController
Tab
Parallel top-level sections
UITabBarController, TabView
BottomNavigation, TabRow
Drawer
Side menu for global nav
Custom / third-party
NavigationDrawer, modal sheet patterns
Modal
Interruptive flows
sheet, fullScreenCover, present
Dialog, bottom sheet, ModalBottomSheet
Deep linking
URL → screen
Universal Links, onOpenURL
App Links, intent filters, Compose deep links
Universal / app links
HTTPS opens app
Associated Domains, AASA file
Digital Asset Links, assetlinks.json
Dependency injection on mobile
Approach
Platform
Strengths
Trade-offs
Dagger / Hilt
Android
Compile-time graph, scopes, test modules
Learning curve, codegen
Swinject
iOS
Lightweight container, storyboard-free
Runtime resolution; less compile safety
GetIt
Flutter
Simple service locator, fast to adopt
Locator anti-pattern if abused
Manual DI
All
No magic, explicit constructors
Verbose in large apps; easy to forget wiring
Prefer constructor injection at feature boundaries; use containers for app-wide graphs and test doubles.