MVVM & Redux_Page.2
前言
還記得上一章介紹 Reducer<State, Action> 缺點時提到。
- 沒有 Model 層的接口,不利於 Reuse 與 測試。
- Action 無法串接成 Action Chain,無法循環利用。
這一章節將會引入 Environment 與 Action 循環兩個功能。
Code Review
Utility
└── ViewModelComponents
├── BasicActionExcutorViewModel.swift
├── CellViewModelConfigureHandler.swift
├── ExcuteAction.swift
└── TableViewModelProtocol.swift
Environment
typealias Reducer<State, Action, EnvironmentModel> = (inout State, Action, inout EnvironmentModel)->()
Reducer<State, Action, Environment>
- Environment: Reducer 的第三個參數,提供 Method 與 外部參數的接口。
- 使用策略模式,在執行 reducer 時注入其中,可達到商業邏輯可 Reuse 也可建立 Fake 方便編寫測試。
Action 循環
typealias Reducer<State, Action, EnvironmentModel> = (inout State, Action, inout EnvironmentModel)->(Action)?
class BasicActionExcutorViewModel<State, Action, EnvironmentModel>: ActionExcutor {
func excute(_ action: Action) {
if let action = reducer(&state, action, &environment) {
excute(action)
}
}
}
// 正確 example:
let reducer = Reducer { state, action, envi in
switch action {
case a:
// do something
return Action.c
case b:
// do something.
return Action.c
case c:
// do something
return nil
}
}
// 錯誤example :
let reducer = Reducer { state, action, envi in
switch action {
case a:
// do something
return Action.b
case b:
// do something.
return Action.a
case c:
// do something
return nil
}
}
注意:Action.a and Action.b 造成無限循環,在設計時要小心。
Reducer return 下一步動作的 action,再利用 Recursion 機制做遞迴呼叫。 如 BasicActionExcutorViewModel func excute(_ action:) 達到 action 可組裝 與 重復使用。
優點
- Environment 利於測試與reuse
- action 串接讓邏輯可以串接,讓程式碼更易於符合單一原則。(註1)
缺點
- action 無法在異步任務中達成串接功能。
- environment 的封裝異步任務,對於任務管理的需求增加設計難度。
註一:Action 可串接的設計,利於編寫代碼時更易於習慣拆分邏輯,讓method更趨向 unint 的特性
後言:
接下來就不會再優化Reducer 的功能,因為要處理異步的需求的話,以當前的iOS版本,自己編寫輪子工程太大,建議使用功能完整且高度優化的三方庫來達成,比如 SwiftRex, TCA 。