Unidirectional Data Flow — bu nima, UDF Android va iOS da

Muallif: IT Sectr Nashr etilgan: 2026-02-20 O'qish vaqti: 13 daq

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) — holat sikl bo'yicha qat'iy o'zgaradigan arxitektura namunasi: foydalanuvchi kiritishi → Intent → Reducer → yangi State → View ni qayta chizish.
  • Android da UDF ViewModel + StateFlow + Intent qayta ishlash orqali amalga oshiriladi; iOS da — @Observable + Reducer namunasi (Composable Architecture) orqali.
  • Google 2023 yil hujjatlaridan boshlab UDFni Jetpack Compose uchun asosiy arxitektura sifatida tavsiya qiladi.
  • UDF Yagona Haqiqat Manbai (Single Source of Truth) tufayli Ikki Tomonlama Bog'lashning cheksiz sikl muammosini bartaraf qiladi.
  • Asosiy kamchilik — ikki tomonlama bog'lashga nisbatan ko'proq shablon kodi (State, Intent, Reducer, Effect).

Unidirectional Data Flow nima?

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 qanday ishlaydi: State → View → Intent → Reducer sikli

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: ViewModel + StateFlow + Intent

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.

Kotlin
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: TCA va Observable namunasi

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.

Swift
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.

UDF va MVVM: farqi nimada?

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:

XususiyatMVVM (klassik)MVVM + UDF
Ma'lumot oqimiAniqlanmaganQat'iy bir yo'nalishli
Holat o'zgarishiTo'g'ridan-to'g'ri setText() orqaliFaqat Intent → Reducer orqali
Single Source of TruthYo'qHa
Reduktorning test qilinishiPastYuqori (sof funksiya)
Google tavsiyasiEskirgan yondashuvCompose uchun asosiy

UDF joriy etishdagi odatiy xatolar

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

UDF MVI dan qanday farq qiladi?

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 qachon ortiqcha?

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.

UDF ni qanday test qilish kerak?

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.

UDF va Two-Way Binding ni birlashtirish mumkinmi?

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).

UDF, Redux va Elm da umumiylik nima?

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

  • Unidirectional Data Flow (UDF) — State → View → Intent → Reducer bir yo'nalishli sikli bilan holat o'zgarishlarining bashorat qilinishini ta'minlovchi na'muna.
  • Android da UDF ViewModel + StateFlow + sealed class Intent orqali, iOS da esa TCA (Reducer + Store) yoki mahalliy Observable bilan amalga oshiriladi.
  • Google 2023 yildan boshlab UDFni Jetpack Compose uchun asosiy arxitektura sifatida tavsiya qiladi.
  • Reducer — yon ta'sirlarsiz sof funksiya; barcha tarmoq so'rovlari va ma'lumotlar bazasi operatsiyalari Effect qatlamiga chiqariladi.
  • UDF Intent larning aniq qayta ishlanishi va Single Source of Truth tufayli Ikki Tomonlama Bog'lashning cheksiz sikl muammosini bartaraf qiladi.
  • Asosiy xavflar — Reducer dagi yon ta'sirlar, haddan tashqari batafsil Intent lar va tugallanmagan korutinlar.
  • Gibrid yondashuv (formada mahalliy Two-Way Binding + global UDF) aksariyat tijoriy ilovalar uchun optimaldir.

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.

Loyihani muhokama qilish

Shuningdek o'qing