Slide 1

Slide 1 text

MVC⇢MVVM⇢MVVMC 開發經驗分享 iPlayground 2019 @nghuiqin

Slide 2

Slide 2 text

⾃肥時間 • NG(⾺來⻄亞⼈) • Develop from iOS 6, 7 • 在台灣⼯作快滿5年

Slide 3

Slide 3 text

前⾔ 我沒有要說MVC的壞話 MVC其實是很多巨頭APP的根基

Slide 4

Slide 4 text

簡介 • MVC介紹 → 常犯的問題 → 如何避免和維護 • MVVM解決什麼 → 實戰⼼得 → 優化 • MVVMC再進化 → 實戰⼼得 → 要注意的坑

Slide 5

Slide 5 text

Model View Controller MVC

Slide 6

Slide 6 text

MVC常遇到的問題

Slide 7

Slide 7 text

Controller 背負的責任 Fetch models Views layout Business Logic Routing Logic Selectors (Handle actions) Miscellaneous (Location, Map, Event…) Delegates

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

如何 減輕Controller的負擔

Slide 11

Slide 11 text

有些職責Model該做 Fat Model Skinny Controller

Slide 12

Slide 12 text

模組化設計 → reusability

Slide 13

Slide 13 text

Utilities APIManager IAPHelper LocationManager AccountManager Reachability iCloudManager Singletons

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

Extension (Category)

Slide 16

Slide 16 text

程式的品質 Code Quality UNIT TEST

Slide 17

Slide 17 text

View Controller View Business Logic Account State MVC 寫測試遇到瓶頸 Controller 會帶⼀些我們 不需要的Code Business Logic 有可能被 其他View/Object影響 …

Slide 18

Slide 18 text

Model View Controller MVC MVVM Model ViewModel View
 (Controller)

Slide 19

Slide 19 text

Controller 背負的責任 Fetch models Views layout Business Logic Routing Logic Selectors (Handle actions) Miscellaneous (Location, Map, Event…) Delegates

Slide 20

Slide 20 text

MVVM - Controller ⼯作量 initViewModel Views layout Routing Logic Selectors (Handle actions) Delegates

Slide 21

Slide 21 text

MVVM Model ViewModel View
 (Controller) 我很單純

Slide 22

Slide 22 text

ViewModel Binding to View → → → →

Slide 23

Slide 23 text

Unit Test Controller Business Logic Account State ViewModel View … 就有理由不⽤寫 Controller的單元測試

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

MVVM 實戰經驗談 我遇過的問題

Slide 26

Slide 26 text

是不是所有View都需要 ViewModel? 不需要 簡單的畫⾯可以省略

Slide 27

Slide 27 text

畫⾯複雜ViewModel好肥 StreamRoomViewModel 不負責任的假設 如果你的畫⾯跟17 App⼀樣很炫炮 MessageBox ViewModel GiftPanel ViewModel RankingViewModel AnimationViewModel 沒有⼈⽣來就可以寫完美的code, 持續 refactor 吧 GO!

Slide 28

Slide 28 text

設計上比MVC花更多時間 某種程度上強迫你去理解完整的商業邏輯 先別動⼿寫Code,先思考。 畫好你的框架再填入內容

Slide 29

Slide 29 text

ViewModel 處理的資料/狀態 變多的時候... 我還是讀得朦傻傻

Slide 30

Slide 30 text

ViewModel 優化 更好讀、測試更好寫 順便釐清責任

Slide 31

Slide 31 text

Inputs/Outputs Protocol 始於Kickstarter在Java&Swift設計的⼀個VM structure https://github.com/kickstarter/native-docs/blob/master/vm-structure.md

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

實作ViewModel ⽤Input約束其他物件的控制 ⽤Output約束出⼝,只做readOnly

Slide 34

Slide 34 text

Binding的時候也好讀

Slide 35

Slide 35 text

寫Unit Test的時候也簡單

Slide 36

Slide 36 text

Model View Controller MVC MVVM Model ViewModel View
 (Controller) MVVMC Model ViewModel View
 (Controller) Coordinator

Slide 37

Slide 37 text

MVVMC 變形有很多種 我個⼈使⽤的是Green⼤⼤寫的Coordinator (比較單純,沒太多元素) https://github.com/nghuiqin/Todo-RxSwift-MVVMC/tree/master/Library

Slide 38

Slide 38 text

MVVM - Controller 責任 initViewModel Views layout Routing Logic Selectors (Handle actions) Delegates

Slide 39

Slide 39 text

Controller 責任-1 initViewModel Views layout Selectors (Handle actions) Delegates Routing logic Coordinator initVC

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

Controller 增加可重複使⽤性

Slide 42

Slide 42 text

Controller 責任-1 initViewModel Views layout Selectors (Handle actions) Delegates Routing logic Coordinator initVC 視情況⽽定

Slide 43

Slide 43 text

App Coordinator Login Coordinator MainTab Coordinator Register Coordinator Home Coordinator Setting Coordinator Detail Coordinator

Slide 44

Slide 44 text

Dependency Injection 消滅Singleton的存在

Slide 45

Slide 45 text

Singleton 的隱患 關聯性問題 Coupling Issue → 到底是誰改了它的值? → 想像⼀下Global Variable的可怕,海底撈針 → 寫測試的時候,它的狀態要怎麼控制?(難)

Slide 46

Slide 46 text

定義App Dependency 靠Coordinator指派下去

Slide 47

Slide 47 text

在ViewModel/View裡 設計Dependency的取⽤

Slide 48

Slide 48 text

DI + Protocol 簡化 單元測試

Slide 49

Slide 49 text

現在我可以⾃由決定這個ViewModel的狀態 ⽬標就是測試ViewModel + Dependency邏輯正確

Slide 50

Slide 50 text

建議DateFormatter也可以當 Utilities Dependency

Slide 51

Slide 51 text

蘋果在這裏告訴你DateFormatter很貴 https://developer.apple.com/library/archive/documentation/Cocoa/ Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html

Slide 52

Slide 52 text

寫MVVMC可能 會遇到的坑

Slide 53

Slide 53 text

不建議使⽤xib/Storyboard 為了讓Dependency inject起來漂亮

Slide 54

Slide 54 text

Coordinator 注意回收的問題 依你使⽤的Coordinator的設計⽽定 我的情況是在原⽣回到上⼀⾴時下需要特別處理 另外就是可能被ViewController/ViewModel retain

Slide 55

Slide 55 text

AppDependency傳入的⽅法 由於Coordinator是有層層關係 App → B → C → D 如果只有D需要dependency的東⻄ B、C的Coordinator也會需要帶

Slide 56

Slide 56 text

MVVMC學習成本頗⾼ 真諦是理解為什麼要這樣設計 好像離⼤神更進⼀⼩步了 以後⾯試拿出來說嘴 (X

Slide 57

Slide 57 text

• 選擇適合你團隊的架構 • 沒接觸過MVVM的話,可先從MVVM開始 • 有必要跟風MVVMC嗎? 看團隊意願 • 個⼈建議全新專案 + 團隊認可這個⽅案 • ⼀⼈團隊沒有太多時間QAQ: MVC其實也不賴啦 結語

Slide 58

Slide 58 text

“Keep it simple, stupid.” 先從簡單的開始

Slide 59

Slide 59 text

References Follow Green • Github: @Greenchiu , Twitter: @handkid Kickstarter Inputs/Outputs Protocol • https://github.com/kickstarter/native-docs/blob/master/ vm-structure.md 想要了解更多MVVMC實作,可以參考我的練習 • https://github.com/nghuiqin/Todo-RxSwift-MVVMC/