Ответ
Однонаправленный поток данных (Unidirectional Data Flow, UDF) — это архитектурный паттерн, при котором данные в приложении циркулируют в одном предсказуемом направлении: от источника состояния (State) к представлению (View) и обратно через строго определенные действия (Actions).
Ключевой принцип:
- Состояние (State) — единственный источник истины для UI.
- Представление (View) — отображает состояние и отправляет действия (Actions) при событиях от пользователя.
- Редьюсер (Reducer) — чистая функция, которая принимает текущее состояние и действие, возвращая новое состояние.
Пример на SwiftUI с архитектурой, похожей на Redux:
// 1. Состояние (State)
struct AppState {
var counter: Int = 0
}
// 2. Действия (Actions)
enum AppAction {
case increment
case decrement
}
// 3. Редьюсер (Reducer)
func appReducer(state: inout AppState, action: AppAction) {
switch action {
case .increment:
state.counter += 1
case .decrement:
state.counter -= 1
}
}
// 4. Хранилище (Store) и Представление (View)
import SwiftUI
import Combine
final class Store: ObservableObject {
@Published private(set) var state: AppState
init(state: AppState = AppState()) {
self.state = state
}
func send(_ action: AppAction) {
appReducer(state: &state, action: action) // Данные обновляются здесь
}
}
struct CounterView: View {
@EnvironmentObject var store: Store
var body: some View {
VStack {
Text("Счетчик: (store.state.counter)") // Данные читаются
Button("+") { store.send(.increment) } // Действие отправляется
Button("-") { store.send(.decrement) }
}
}
}
Преимущества:
- Предсказуемость: Легко отследить, как и почему изменилось состояние.
- Тестируемость: Редьюсеры — чистые функции, их легко тестировать изолированно.
- Отладка: Централизованное состояние упрощает логирование и инструментирование (например, time-travel debugging).
- Согласованность UI: Все представления синхронизированы с одним источником состояния.
Где используется: Redux (JavaScript), The Composable Architecture (TCA, Swift), Flux, а также является базовым принципом управления состоянием в SwiftUI через @State, @ObservableObject и @EnvironmentObject.