MVVM重構(gòu)

ViewModel 重構(gòu)檢查清單

識(shí)別壞味道:

1.直接訪問(wèn)全局變量(kIsVip)

2.一個(gè)類承擔(dān)了太多職責(zé)(數(shù)據(jù)處理,插入廣告,Vip狀態(tài))

3.函數(shù)長(zhǎng)度超過(guò) 50 行

4.太多 mutable var(狀態(tài)混亂)

5.直接使用單例 (BannerADHelp.shared、MainDataHelp.shared)

提取Input/Output:

定義 Input(所有外部傳入的依賴)

定義 Output(View 需要顯示的數(shù)據(jù))

定義 ViewModel

定義協(xié)議(依賴倒置)

黃金法則: 每個(gè)外部依賴都要有協(xié)議

?3.1 列出所有外部依賴 (BannerADHelp.shared??Device.isIpad?kIsVip)

3.2 為每個(gè)創(chuàng)建協(xié)議

protocol AdServiceProtocol {

? ? func canRequestAD(for enter: ADEnterType) -> Bool

? ? func getAdModel() -> ComponentADModel

}

// 3.3 創(chuàng)建真實(shí)實(shí)現(xiàn)(包裝原有代碼)

class DefaultAdService: AdServiceProtocol {

? ? func canRequestAD(for enter: ADEnterType) -> Bool {

? ? ? ? BannerADHelp.shared.canRequestAD(enter: enter)? // ?? 只在這里調(diào)用

? ? }

}

處理?xiàng)l件判斷?

壞味道就是一堆 if-else

編寫測(cè)試

測(cè)試是重構(gòu)的保障!

// 6.1 創(chuàng)建 Mock

class MockAdService: AdServiceProtocol {

? ? var canRequestADResult = false

? ? func canRequestAD(for enter: ADEnterType) -> Bool {

? ? ? ? return canRequestADResult

? ? }

}

使用:

let mockAd = MockAdService()

mockAd.canRequestADResult = true

?? 記住這個(gè)口訣

找出依賴 → 定義協(xié)議

創(chuàng)建 Input → 注入依賴

分離職責(zé) → 一個(gè)類做一件事

計(jì)算屬性 → 替代存儲(chǔ)屬性

寫測(cè)試 → 驗(yàn)證重構(gòu)正確


最后建議

不要一次全改:先抽最簡(jiǎn)單的依賴(如Device.isIpad)

寫一個(gè)測(cè)試用例:確保重構(gòu)后功能不變

逐步替換:先用新 ViewModel 在簡(jiǎn)單頁(yè)面

團(tuán)隊(duì)同步:和大家分享你的重構(gòu)模式

核心思想ViewModel 應(yīng)該像函數(shù)一樣——輸入明確,輸出明確,不依賴全局狀態(tài)。每次寫 ViewModel 時(shí)問(wèn)問(wèn)自己:“這個(gè)類能在測(cè)試中單獨(dú)運(yùn)行嗎?”

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容