iOS 工程

[iOS 架構 #5] iOS VIPER 架構:大型 App 為何導入後又離開(直到 RIBs)

在 iOS 架構的討論中,很少有模式像 VIPER 一樣引發如此兩極的評價。

閱讀 4 分鐘
[iOS 架構 #5] iOS VIPER 架構:大型 App 為何導入後又離開(直到 RIBs) 封面圖

在 iOS 架構的討論中,很少有模式像 VIPER 一樣引發如此兩極的評價。

有人稱它是「大型團隊協作的解答」,也有人稱它是「樣板碼地獄」。實際上,不少大型服務 App 曾在某個時期導入 VIPER 或其變體,幾年後又轉向更輕量的架構。

今天來整理 VIPER 想解決什麼問題,以及為什麼代價如此高昂。


VIPER 由五個部分組成

VIPER 將一個畫面拆成五種角色,名稱本身就是這五個角色的字首。

  • View:負責顯示畫面,包含檢視控制器,只「負責繪製」。
  • Interactor:商業邏輯。取得資料並套用規則。
  • Presenter:View 與 Interactor 之間的中介,將資料加工成畫面所需的形式。
  • Entity:純資料模型。
  • Router(Wireframe):負責畫面轉場。

它把 MVC(Model-View-Controller)中原本由一個檢視控制器負責的工作拆成四部分,並將畫面轉場另外抽成 Router。也就是為系列第 1 篇提到的 Massive View Controller 每項責任都安排專屬位置。

核心規則是近似單向的嚴格參照關係。View 只知道 Presenter,Presenter 知道 Interactor 和 Router,而 Interactor 只接觸 Entity。各邊界以協定切開,因此任何部分都能替換成 mock。


有哪些改善?

這種架構確實有發揮光彩的時刻。

第一,能將測試涵蓋率提升到極致。所有邊界都是協定,因此 Interactor、Presenter、Router 都能各自獨立測試。

第二,大型團隊的分工更容易。每個畫面的結構都相同,因此可以預期「不論誰製作的畫面,檔案配置都一樣」。數十人共同維護一個程式碼庫時,這種一致性確實有價值。

第三,它很適合以功能為單位的模組化。一個畫面是自成一體的五個部分,因此容易依功能抽出模組。Uber 受 VIPER 啟發打造的 RIBs,就是將這個方向推到極致的案例:不是按 View,而是按商業邏輯單位將 App 拆成樹狀結構。

即使只有一個按鈕的畫面,也會被強制拆成同樣的五個部分
即使只有一個按鈕的畫面,也會被強制拆成同樣的五個部分

為什麼大家都離開了?

問題在於成本。

樣板碼多得驚人。即使是只有一個按鈕的畫面,View、Interactor、Presenter、Entity、Router,加上彼此之間的協定,也會產生六、七個檔案。「改一個標籤文字要經過三個檔案」之所以成為抱怨,並非沒有原因。

即使是簡單畫面,也會被強制承擔同樣的重量。靜態設定畫面和複雜動態消息畫面都一樣是五個部分。畫面的複雜度與架構重量並不成比例。

學習曲線與上手成本也不低。第一次看見資料沿著 View → Presenter → Interactor → Presenter → View 往返的人,需要一些時間才能追蹤這段流程。

而真正的致命一擊是SwiftUI 的出現。VIPER 源自 UIKit 時代「把責任從檢視控制器移出」的問題意識;但在 SwiftUI 中,View 本身已經很輕量,畫面轉場方式也不同,因此 Router 這類部分變得不自然。問題本身已經改變了。


所以 VIPER 是失敗的模式嗎?

很難這樣看。因為 VIPER 留下的遺產已融入現今的標準實務。

  • 將畫面轉場交給專責物件 → 發展為 Coordinator 模式
  • 將商業邏輯與呈現分離 → 發展為 UseCase/Repository 層
  • 用協定切開邊界 → 發展為相依性注入與測試實務

完整使用 VIPER 五個部分的團隊變少了,但那五個部分各自想解決的問題與解法都保留了下來。現在更接近只挑選需要部分來使用的時代。

整體雖然退場了,但實用的部分仍成為標準實務
整體雖然退場了,但實用的部分仍成為標準實務

總結

  • VIPER 將一個畫面分成 View、Interactor、Presenter、Entity、Router 五個部分,並以協定切開各邊界。
  • 容易測試及大型團隊的一致性是它的優點,但每個畫面需要六、七個檔案,樣板碼成本很高。
  • 進入 SwiftUI 時代後,問題意識本身改變了,因此完整採用原始 VIPER 的團隊變少。
  • 不過,它的遺產仍以標準實務存留下來,例如 Router→Coordinator、Interactor→UseCase。

下一篇將介紹這項遺產中最普及的形式:Clean Architecture 的 UseCase 與 Repository 在 iOS 中實際負責什麼。

延伸閱讀