Unidirectional Data Flow — bir yo'nalishli ma'lumot oqimi, ma'lumotlar State → View → Intent → Reducer → State yopiq siklida teskari aloqasiz harakatlanadigan arxitektura namunasi. Ikki tomonlama bog'lashdan farqli o'laroq, UDF holat o'zgarishi faqat aniq harakatlar (Intent/Event) orqali sodir bo'lishini kafolatlaydi, bu esa ma'lumot oqimini bashorat qilinadigan va kuzatiladigan qiladi. Google I/O 2024 ma'lumotiga ko'ra, UDF o'rta va yuqori murakkablikdagi biznes-mantiqqa ega Jetpack Compose va SwiftUI ilovalari uchun tavsiya etilgan arxitekturadir.
Asosiy
Unidirectional Data Flow (UDF) — ma'lumotlar yopiq sikl bo'ylab bir yo'nalishda harakatlanadigan, View va Model o'rtasidagi teskari aloqani istisno qiladigan arxitektura namunasi. UI dagi o'zgarish darhol modelni yangilaydigan Ikki Tomonlama Bog'lashdan farqli o'laroq, UDF har bir holat o'zgarishi uchun aniq harakat (Intent, Event, Action) talab qiladi. Bu ma'lumot oqimini to'liq bashorat qilinadigan qiladi: istalgan vaqtda qaysi harakat joriy holatga olib kelganini aniqlash mumkin.
UDF kontseptsiyasi veb-freymvorklardan — Redux (JavaScript, 2015) va Elm (2012) — kelgan va mobil ishlanma uchun moslashtirilgan. Google I/O 2024 ma'lumotiga ko'ra, UDF Jetpack Compose uchun tavsiya etilgan arxitekturaga aylanib, klassik MVVM ni LiveData bilan almashtirdi. iOS da shunday yondashuv Point-Free kompaniyasining The Composable Architecture (TCA) da amalga oshirilgan bo'lib, Swift Community (2024) so'roviga ko'ra iOS ishlab chiqaruvchilarning 15% dan ortig'i undan foydalanadi.
UDF ning asosiy afzalligi — Single Source of Truth (SSOT): ilovaning barcha holati bir joyda saqlanadi va qat'iy belgilangan operatsiyalar orqali o'zgartiriladi. Bu disk raskadrovka, test va xatolarni qayta tiklashni soddalashtiradi, chunki har bir holat o'zgarishi qayd etiladi va xuddi shu Intent larni qayta yuborish orqali qayta tiklanishi mumkin.
UDF ning asosiy sikli to'rt bosqichdan iborat: State (joriy holat) View da ko'rsatiladi; foydalanuvchi harakat qiladi, bu Intent (niyat) ga aylanadi; Intent Reducer (sof funksiya) da qayta ishlanadi va yangi State yaratadi; yangi holat qayta chizish uchun View ga uzatiladi. Bu sikl har bir foydalanuvchi yoki tizim hodisasida takrorlanadi.
Tsiklning har bir elementi qat'iy javobgarlikka ega: State — ekranning ma'lum bir andagi holatini tavsiflovchi o'zgarmas (immutable) ob'ekt; View — State ni ko'rsatuvchi funksiya; Intent — foydalanuvchining niyatini tavsiflovchi qiymat (masalan, LoginIntent.Submit); Reducer — yon ta'sirlarsiz sof funksiya, joriy State va Intent ni qabul qilib, yangi State qaytaradi. Yon ta'sirlar (tarmoq so'rovlari, ma'lumotlar bazasi) alohida Middleware yoki Effect qatlamiga chiqariladi.
Google Android Architecture (2024) maqolasiga ko'ra, Reducer ning sofligi asosiy talabdir: agar Reducer tarmoq chaqiruvi yoki ma'lumotlar bazasiga yozishni o'z ichiga olsa, ma'lumot oqimini test qilish va tuzatish imkonsiz bo'ladi. Barcha yon ta'sirlar Reducer chaqirilishidan oldin ViewModel korutini yoki Swift Task da bajarilishi kerak, natija esa yangi Intent sifatida yuborilishi kerak.
Android da UDF ni amalga oshirish uchta Jetpack komponentiga asoslanadi: ViewModel hayot siklini boshqaradi, StateFlow reaktiv holat oqimini ta'minlaydi, Intent (sealed class) barcha mumkin bo'lgan foydalanuvchi harakatlarini tavsiflaydi. View StateFlow ga Compose da collectAsState() yoki View tizimida observe() orqali obuna bo'ladi.
sealed class LoginIntent {
data object Submit : LoginIntent()
data class UpdateEmail(val value: String) : LoginIntent()
data class UpdatePassword(val value: String) : LoginIntent()
}
data class LoginState(
val email: String = "",
val password: String = "",
val isLoading: Boolean = false,
val error: String? = null
)
class LoginViewModel : ViewModel() {
private val _state = MutableStateFlow(LoginState())
val state: StateFlow<LoginState> = _state.asStateFlow()
fun onIntent(intent: LoginIntent) {
when (intent) {
is LoginIntent.UpdateEmail -> {
_state.update { it.copy(email = intent.value) }
}
is LoginIntent.UpdatePassword -> {
_state.update { it.copy(password = intent.value) }
}
is LoginIntent.Submit -> {
_state.update { it.copy(isLoading = true, error = null) }
loginUseCase(_state.value.email, _state.value.password)
.onSuccess {
_state.update { it.copy(isLoading = false) }
}
.onFailure { e ->
_state.update { it.copy(isLoading = false, error = e.message) }
}
}
}
}
}
@Composable
fun LoginScreen(viewModel: LoginViewModel) {
val state by viewModel.state.collectAsState()
LoginForm(
email = state.email,
onEmailChange = { viewModel.onIntent(LoginIntent.UpdateEmail(it)) },
password = state.password,
onPasswordChange = { viewModel.onIntent(LoginIntent.UpdatePassword(it)) },
isLoading = state.isLoading,
onSubmit = { viewModel.onIntent(LoginIntent.Submit) }
)
}Misol Android da to'liq UDF siklini ko'rsatadi: LoginIntent barcha mumkin bo'lgan harakatlarni tavsiflaydi (email o'zgartirish, parol o'zgartirish, formani yuborish), LoginState — o'zgarmas holat, LoginViewModel Intent larni qayta ishlaydi va StateFlow ni yangilaydi, Compose ekrani esa state ni collectAsState() orqali obuna qiladi. Har bir holat o'zgarishi ma'lum bir Intent ni qayta ishlash natijasidir, bu ma'lumot oqimini to'liq shaffof qiladi.
iOS da UDF The Composable Architecture (TCA) Point-Free yoki iOS 17+ dan boshlab mahalliy Observable namunasi orqali amalga oshiriladi. TCA tayyor State + Action + Reducer + Store siklini taqdim etadi, bu erda Store yagona haqiqat manbai, View esa @Observable yoki ObservableObject orqali o'zgarishlarga obuna bo'ladi.
struct LoginState: Equatable {
var email = ""
var password = ""
var isLoading = false
var error: String?
}
enum LoginAction {
case emailChanged(String)
case passwordChanged(String)
case submit
case loginResponse(Result<User, Error>)
}
let loginReducer = Reducer<LoginState, LoginAction> { state, action in
switch action {
case .emailChanged(let email):
state.email = email
return .none
case .passwordChanged(let password):
state.password = password
return .none
case .submit:
state.isLoading = true
state.error = nil
return .run { send in
let result = await loginUseCase(state.email, state.password)
await send(.loginResponse(result))
}
case .loginResponse(.success):
state.isLoading = false
return .none
case .loginResponse(.failure(let error)):
state.isLoading = false
state.error = error.localizedDescription
return .none
}
}
struct LoginView: View {
let store: StoreOf<LoginReducer>
var body: some View {
WithViewStore(store, observe: { $0 }) { viewStore in
Form {
TextField("Email", text: viewStore.binding(get: \.email, send: { .emailChanged($0) }))
SecureField("Password", text: viewStore.binding(get: \.password, send: { .passwordChanged($0) }))
Button("Kirish") { viewStore.send(.submit) }
}
}
}
}loginReducer reduktori — sof funksiya: tarmoq so'rovlarini to'g'ridan-to'g'ri bajarmaydi, balki TCA muhiti tomonidan bajariladigan Effect ni qaytaradi. Bu reduktorni izolyatsiya qilingan holda test qilish, testlarda effektlarni almashtirish imkonini beradi. View WithViewStore orqali Store o'zgarishlariga obuna bo'ladi va send() orqali Action yuboradi. TCA Store yo'q qilinganda effektlarning bekor qilinishini avtomatik boshqaradi, xotira oqishining oldini oladi.
MVVM va UDF ko'pincha chalkashtiriladi, ammo ular o'rtasida tub farq bor. MVVM — strukturaviy na'munadir, kodni uch qatlamga (Model, View, ViewModel) ajratadi, lekin ma'lumot oqimining yo'nalishini aniqlamaydi. UDF — xatti-harakat namunasi, ma'lumotlarning ushbu struktura ichida qanday harakatlanishini tavsiflaydi. LiveData bilan MVVM da ham ikki tomonlama bog'lash, ham bir yo'nalishli oqim bo'lishi mumkin — UDF MVVM ga Intent ni qayta ishlash uchun qat'iy qoidalar qo'shadi.
Android Developers (2024) hujjatlariga ko'ra, Compose uchun tavsiya etilgan arxitektura MVVM ichidagi UDF dir: ViewModel State ni saqlaydi va Intent larni qayta ishlaydi, View State ga obuna bo'ladi va Intent yuboradi. DataBinding orqali Ikki Tomonlama Bog'lash bilan klassik MVVM Google tomonidan faqat biznes-mantiqsiz oddiy ekranlar uchun tavsiya qilinadi. Jetpack Compose uchun asosiy stsenariy aniq hodisalarni qayta ishlash bilan UDF dir.
Taqqoslash jadvali:
| Xususiyat | MVVM (klassik) | MVVM + UDF |
|---|---|---|
| Ma'lumot oqimi | Aniqlanmagan | Qat'iy bir yo'nalishli |
| Holat o'zgarishi | To'g'ridan-to'g'ri setText() orqali | Faqat Intent → Reducer orqali |
| Single Source of Truth | Yo'q | Ha |
| Reduktorning test qilinishi | Past | Yuqori (sof funksiya) |
| Google tavsiyasi | Eskirgan yondashuv | Compose uchun asosiy |
Eng keng tarqalgan xato — Reducer ichidagi yon ta'sirlar. MVVM ga o'rganib qolgan ishlab chiqaruvchilar tarmoq so'rovlarini to'g'ridan-to'g'ri Intent handleriga joylashtiradi, bu Reducerni nopok funksiyaga aylantiradi va test qilish imkoniyatini buzadi. Barcha effektlar qiymat (Effect / SideEffect) sifatida qaytarilishi va freymvork infrastrukturasi tomonidan bajarilishi kerak. Android da buning uchun ViewModel dagi korutinlar, TCA da esa Effect.run ishlatiladi.
Ikkinchi xato — haddan tashqari batafsil Intent lar. Har bir tugma bosilishi, slayder siljishi va matn o'zgarishi alohida Intent yaratadi. Kiritish maydonlari uchun bu haddan tashqari ko'p — bunday hollarda forma ichida bir yo'nalishli oqim bilan Binding dan foydalanish (lokal holat) maqbuldir, global Intent esa faqat muhim harakatlarda (yuborish, navigatsiya) yuboriladi.
Uchinchi xato — effektlarni bekor qilishning yo'qligi. Agar foydalanuvchi ekranni tark etsa-yu, korutin yoki Task ishlashda davom etsa, natija allaqachon yo'q qilingan View ga qo'llanilishi mumkin. Android da viewModelScope.cancel() yoki takeWhileActive() dan foydalaning; TCA da effektlar Store yo'q qilinganda avtomatik bekor qilinadi. Google Issue Tracker (2024) ma'lumotiga ko'ra, tugallanmagan korutinlardan oqishlar Compose ilovalarining ishdan chiqish sabablarining top-5 taligiga kiradi.
Tez-tez so'raladigan savollar
MVI (Model-View-Intent) — uchta majburiy elementga ega UDF ning alohida holati: Intent (niyat), Model (holat), View (ko'rinish). Asosiy farq shundaki, MVI da ekranning har bir holati bitta o'zgarmas struktura (Sealed class) bilan tavsiflanadi, View esa Model dan UI ga sof funksiyadir. UDF — Redux va Elm ni o'z ichiga olgan har qanday bir yo'nalishli oqimni tavsiflovchi kengroq atama. Google hujjatlarida UDF atamasi umumiy nom, MVI esa aniq tatbiq sifatida ishlatiladi.
UDF validatsiyasiz bitta kiritish maydoni bo'lgan ekranlar, statik sahifalar va placeholder ekranlar uchun ortiqcha. Agar ekranda biznes-mantiq bo'lmasa va uning holati foydalanuvchi harakatlariga bog'liq bo'lmasa, UDF foydasiz kod qo'shadi. Bunday stsenariylar uchun bir yo'nalishli bog'lash yoki SwiftUI da oddiy @State yetarli. UDF ekranning mumkin bo'lgan holatlari soni 3–4 dan oshganda va/yoki yon ta'sirlar mavjud bo'lganda asoslanadi.
Reducer sof funksiya bo'lgani uchun uni test qilish State va Intent ning turli kombinatsiyalari bilan chaqirish va natijaviy State va Effect ni tekshirishdan iborat. Android da StateFlow ni test qilish uchun Turbine dan foydalaning: Intent yuboring, keyingi State emissiyasini tekshiring. TCA da o'rnatilgan TestStore mavjud bo'lib, u Action dan keyin faqat kutilgan State maydonlari o'zgarganligini va faqat kutilgan Effect lar bajarilganligini avtomatik tekshiradi.
Ha, birlashtirish mumkin va ko'pincha optimaldir. Forma ichidagi kiritish maydonlari uchun har bir tugma bosilishida Intent yaratmaslik uchun mahalliy Two-Way Binding (yoki SwiftUI da Binding) dan foydalaning. Forma yuborilganda Reducer tomonidan qayta ishlanadigan to'plangan ma'lumotlar bilan bitta Intent yuboring. Ushbu gibrid yondashuv — global UDF mahalliy Two-Way Binding bilan — tijoriy SwiftUI ilovalarining 70 foizida qo'llaniladi (Swift Community Survey 2024 ma'lumotlari).
Uchala na'muna ham yagona haqiqat manbai bilan bir yo'nalishli ma'lumot oqimini amalga oshiradi. Elm (2012) — sof Model → View → Update siklini birinchi bo'lib taqdim etgan funksional til. Redux (2015) Elm ni Store, Reducer va Action konsepti bilan JavaScript ga moslashtirdi. UDF bu g'oyalarning mobil ishlanma uchun umumlashtirilishidir. Uchala yondashuv ham holatning bo'linmas (atomik) yangilanishlari orqali o'zgarishlarning bashorat qilinishini kafolatlaydi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.