閒談軟體設計:Model Model Model

2024/03/02閱讀時間約 5 分鐘


可能是過去求學時,學的是《Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development》和《Object-Oriented Modeling and Design with UML, 2nd》書中描述的方式做物件分析與設計,從 use case 描述中抓出名詞成為 domain model,從動詞找出類別的行為和物件間的關聯,用 GRASP 原則將責任分配到合適的類別身上,但這個 domain model 離實際的 implementation model 還有段距離,畢竟還要跟使用的框架打交道。


就業後,對於 Model 這字眼總是特別小心,有趣的是,Model 其實沒什麼嚴格的定義,所以每個人對 Model 的解讀也不盡相同,有人覺得資料怎麼儲存屬於 Model 的一部份 (受 ORM 工具的影響),有人覺得工作流程 (workflow) 是 Model 的一部份,我個人也有自己的想法,而且隨專案的規模和特性,也不是總是一樣的。

若看 Wikipedia 對 Multitier architecture 的描述,會發現常見的架構分成四層,每一層的責任似乎明確卻又有一點模糊,而我自己的見解是:

  • Presentation layer — 若是使用 server-rendering 為主要技術的框架中,這一層主要是將 application layer 的結果轉換成 HTML;若是在桌面應用程式或是 client-rendering 中,這一層主要就是 UI 相關的邏輯 (跳出對話框、切換視窗、更新視窗中的元件)。
  • Application layer — 如 Wikipedia 的描述,我亦是把這一層當作 GRASP 的 system event controller (此 controller 不等同 MVC 的 controller),並處理完成一個 use case 中非 domain (business) logic 的其他部分,例如:發送信件 (通知)、關係注入 (dependency injection)、infrastructure 或外部系統的調用、request 資料格式的檢查等。
  • Business layer — 基本上這一層只處理 domain objects 間的 relationship 以及確保最終狀態是符合 business rules,例如:在一個論文審查系統中,不能將一篇直接從 wait for review 移到 accepted 或 rejected (至少要經過審查)。
  • Data access layer — 這一層除了處理資料怎麼儲存 (persistence) 外,也包含如何從網路存取外部的資料。而在 persistence 這件事上,個人比較偏好 Repository pattern。

雖然這樣看起來,四層很明確啊!但實際在寫程式時,還是會有一些模糊的空間,有時候還是要思考這一段程式應該放在哪一層,特別是 application layer 和 business layer 之間更是如此;因此,也可以說,每個人對於 Model 到底是包含 application layer 還是 business layer 的哪些部分看法不太一致,對我來說,二者都是 Model,但若分成四層,二者不會是同一個物件。

程式的結構 (以目錄或其他方式呈現) 上,有時也不容易看出結構與分層的對應關係。有時候,強制分成四層也會讓程式架構變複雜,所以我在桌面應用程式或 Mobile App 中,我可能選擇讓 application layer 與 business layer 合併,簡化成三層,或是讓 application layer 非常的薄。

在 Web 應用中,原則上還是分成四層,但個人偏好 client-rendering,因此 presentation layer 通常在 client,不過,為了方便測試,有時候 Web server 端還是會有負責提供 presentation model 的 presentation layer。例如用 Spring 框架來撰寫,application layer 的程式有時會散在 filter (身份認證或權限控管)、interceptor (稽核) 和 request controller (直接當成 system event controller) 中,但原則上 request controller 的程式大多很短,主要邏輯還是在 business layer 裡。

或許,事情不用這麼複雜,在設計每個 class 時或是想將功能加到一個 class 時,用 single responsibility 的原則來思考,適合放在這個 class 嗎?若不合適,應該放在哪裡呢?這時候參考軟體的架構思考應該放在哪一層。在層與層之間的 dependency 該如何管理或注入時,多想想 interface segregation 原則,不要直接依賴實作,甚至可以想一下 dependency inversion 原則,降低上層程式與下層程式的依賴,盡可能讓每一層都能維持獨立,此時,要進行測試就容易多了。

總結來說,對 Model 的解讀可以各自不同,沒什麼標準答案,但不論用什麼方式解讀,只要能讓程式易讀好維護,就是好的設計。

51會員
98內容數
這是從 Medium 開始的一個專題,主要是想用輕鬆閒談的方式,分享這幾年軟體開發的心得,原本比較侷限於軟體架構,但這幾年的文章不僅限於架構,也聊不少流程相關的心得,所以趁換平台,順勢換成閒談軟體設計。
留言0
查看全部
發表第一個留言支持創作者!