打造更好的 MVC (一)
原文:ofollow,noindex">A Better MVC, Part 1: The Problems
我最近讀了@radiantav 的一篇Much ado about iOS architecture 的精彩文章。它觸及到了我腦海中經常出現的一個話題。我在最近的Swift by Northwest 上發表了一篇名為「打造更好的 MVC 」的演講。下面我會用一系列部落格文章來闡述我演講的要點。
我首先要道歉,文章中不會有任何照片。使用圖片肯定會讓主題更加清晰,但我不想花時間去製作它們。你只能多運用你的想象力了。
MVC 的問題
人們譴責 MVC 的主要原因是他們在使用它時往往會遇到兩個主要問題:
- 如 Apple 示例程式碼所述,MVC 鼓勵你違反封裝原則,這最終會導致麵條式程式碼。
- 沒有適當的規則,你的檢視控制器會變得龐大,導致 「MVC」會被大家調侃成「Massive View Controller」。
違反封裝
遇到類似這樣的UITableViewDelegate
方法很常見:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard let item = maybeItem else { return } let detail = MyCustomDetailViewController(item: item) show(detail, sender: self) }
這裡有兩個巨大的違反封裝的問題。
第一個是這行程式碼:
let detail = MyCustomViewController(item: item)
封裝原則表明,一個東西應該只是真正「知道」它所包含的物件。但是,這一行程式碼構建了後續的詳細檢視控制器資訊,這就需要當前檢視控制器知道整個資料流序列。
換句話說,這個列表不僅僅是一個列表,還必須知道它的具體使用方式。
第二個問題跟第一個相似:
show(detail, sender: self)
同樣的,這違反了「不知道你的使用上下文」的原則。並且,你應該注意到,無論你是手動建立,還是呼叫segue
並使用prepareForSegue:sender:
來顯示詳細試圖控制器,這些批評都適用。
Massive View Controller
很遺憾,我們得承認遇到數千行的檢視控制器很常見。我們的試圖控制器很快就會變得混亂,它會充斥著網路回撥、代理方法(delegate methods)、資料來源方法(data source methods)、IBActions
、trait collection reactions、模型資料觀察(model observation)和一些我們的業務邏輯。如果你正在進行任何型別的漸進式載入,並希望通過一個指示器來顯示「正在載入…」,這時候你通常會需要新增幾百行程式碼,管理另一個有載入狀態的屬性。
我們最終會遇到這種情況,因為我們對檢視控制器沒有足夠的規則來約束。它們很快就會變得不可維護、脆弱,而且本質上是不可測試的。試問,誰想除錯一個「5000+」行程式碼的檔案?
解決 MVC 問題
根據我的經驗,這些幾乎是開發人員發現其他架構模式如此吸引人的兩個基本原因。因此,我們轉向其他架構模式來嘗試和修復這些問題。我常見的其它架構模式有 MVVM、React、MVP、FRP、VIPER,或sarchitecture.top" target="_blank" rel="nofollow,noindex">insert-new-architecture-here 。
需要明確的是,這些模式都是沒有問題。它們都使用了某種獨特有趣的方式來解決問題。我們鼓勵大家學習和了解它們。但是我發現基於這些模式構建應用程式往往也會帶來一些負面的影響。
-
所有這些其它的架構模式對於
UIKit
和AppKit
都不是很友好。因為這個問題,你在開發時往往會遇到許多額外的障礙。 - 當你的團隊成員變化時,你還需要額外的工作來向新的開發者講述正在使用的構架模式,而不僅僅是業務邏輯。這需要更多的前期投入,並且在團隊成員開始工作之前需要更長的準備時間。
- 當作業系統發生變化時,你可能也需要一些額外工作來做一些適配。比如,必須檢查大小類、安全佈局邊距、動態型別、本地化、區域設定更改、首選屬性(狀態列樣式等)、生命週期事件、狀態儲存和恢復等等。
- 當你的需求發生變化時,你有時會遇到不得不 fork 其他人的庫、等待他們更新,或者希望他們接受你的 PR 的情況。我不會在這裡討論使用第三方依賴庫的優缺點,但是架構依賴比普通依賴會有更多「問題」要考慮,因為它是用來支撐整個應用程式。
使用其它的架構模式可能使你的程式碼乾淨簡潔。但是,當你越來越遠離系統框架提供的內容時,這意味著當新的系統功能出來時,你需要更多程式碼和更多時間來實現新的功能。
如果你可以只使用UIKit
和AppKit
並且可以解決以上所講的問題,那是不是很棒?如果我們可以生活在一個檢視控制器中的程式碼不會超過300行的世界裡,那是不是很好?
在下一篇文章中,我們將看看如何解決第一個問題。