去model化開發

林欣達發表於2016-07-26

前言

去model化是一種框架設計上的做法,其中的model並不是指架構中的model層,套用Casa大神部落格中的原文就是:

model化就是使用資料物件,去model化就是不使用資料物件。

常見的去model化做法是使用字典儲存資料資訊,然後提供一個reformer負責將這些字典資料轉換成View層可展示的資訊,其流程圖如下:

11783864-44d2740cacb03664

更詳細的理論知識可以看Casa大神的去model化和資料物件。本文基於Casa大神的實踐基礎使用另外一種去model化的實現方式。

使用背景

在很早之前就看過大神的文章,不過一直沒有去嘗試這種做法。在筆者最近跳入新坑之後,總算是有了這麼一次機會。需求是存在著三個非常相似的cell,但分別對應著不同的資料model

12783864-ad13393597f1566b

總結三個cell都需要的展示資料包括:

  • 產品名稱
  • 使用條件
  • 截止日期
  • 背景圖片

此外,優惠資訊屬於第一個和第二個獨有的。現在這一需求存在的問題主要有這麼三點:

三種資料物件在伺服器返回的屬性欄位中命名差別大
這是大部分的應用都存在的一個問題,但是本文中的資料物件有一個顯著的特點是它們對應顯示的cell存在很大的相似度,可以被轉換成相似的展示資料

三種cell可以封裝成一種,卻分別對應著不同的資料物件
這裡涉及cell和資料物件的對接問題,如果cell在以後發生改變了,那麼原有的資料物件是否還能適用

控制器需要在資料來源方法中調配不同的cellmodel,耦合過大
這個也是常見的問題之一,通常可以考慮適用工廠模式將調配的業務分離出去,但在本文中採用去model的方式實現

這些問題都有可能導致專案後期維護的過程中變得難以修改,小小的需求改動都會導致程式碼的大改。筆者的解決方式是制定cellmodel之間對應的兩個協議,從而控制器無需理會兩者的具體型別。

實現

我在上一篇文章MVC架構雜談中提到過M層的業務邏輯放在model中,雖然本文要去model化,但只是去除屬性物件,自身的邏輯處理還保留著。下面是筆者去model化的協議圖以及協議宣告屬性:

13783864-6018c7b456dc63b9

對於本文之中這種存在共同顯示效果的model,可以宣告一個包含多個readonly屬性的協議,讓這些模型物件在協議的getter方法中執行資料->展示這一過程的業務邏輯,而model自身只需簡單的持有字典資料即可:

14783864-e1be8a5475a1ca3c

LXDCouponTicketModel為例,協議的實現程式碼如下:

通過讓三個資料物件實現這個協議,筆者將要展示的資料結果進行統一。在這種情況下,封裝成單個的cell也無需關心model的具體型別是什麼,只需實現針對單元格配置的協議方法獲取展示的資料即可:

三個問題前兩個已經解決了:通過協議統一資料物件的展示效果,這時候並不需要model儲存多個屬性物件,只需要在適當的時候直接從字典中獲取資料並執行資料視覺化這一邏輯即可。cell也不會受限於傳入的引數型別,只需要簡單的呼叫協議方法獲取需要的資料即可。那麼最後一個控制器的協調問題就變得簡單了:

cellmodel共同通過協議的方式實現交流的時候,控制器儲存的資料來源也就可以不關心這些物件的具體型別了。通過泛型宣告多個資料來源,控制器此時的職責僅僅是根據狀態機的改變決定使用哪個資料來源來展示而已。當然,雖然筆者統一了這三個資料來源的型別,但是歸根到底總要根據伺服器返回的json建立不同的資料物件存放到這些資料來源中。如果把這個業務放在控制器中原本就達不到鬆耦合的作用,因此引入一箇中間人Helper來完成這個業務:

去model化之後整個專案的業務流程大致可以用下圖表示:

15783864-bc92af27d055bd7e

這種方式最大的好處在於控制器和檢視不再依賴於model的具體型別,這樣在伺服器返回的json中修改了模型物件欄位的時候,修改ModelProtocol的對應實現即可。甚至在以後的版本再新增現金券各種其他票券的時候,只需要在Helper這一環節新增相應的工廠即可完成改動

尾言

去model化是一種有效快捷的鬆耦合方式,但絕不是萬能藥。在本文的demo中不難看到筆者使用這一方式最大的原因在於多個cell之間有太多的共性而model的屬性欄位全不相同。另一方面在這種設計中Helper可能會因為模型物件的增加變得臃腫,需要謹慎使用。
一個好的專案框架總是隨著需求改變在不斷的調整的,沒有絕對最佳的設計方案。但是嘗試使用不同的思路去搭建專案可以提升我們的認知,培養對於開發框架設計的認識。

關注我的文集iOS開發來獲取筆者文章動態(轉載請註明本文地址及作者)

相關文章