*** 本文同步發表於 FB 社團-軟體設計鮮思維 ***
關於 POC (Proof of Concepts)的說明,可參考:「淺論架構的 POC (Proof of Concepts)」。
關於系統結構設計 (system structure design),個人把它分為兩個構面來看:巨觀與微觀 (Macro/Micro View)。
巨觀結構設計是基於現實系統的分散議題-展示層 (如 Web UI)、永續儲存機制 (如 關聯資料庫),所提出核心業務邏輯應不相依於特定實體元件與實作連結技術的解決方案。這裡推出最實用具應變與可重構的實體分層框架-Enterprise MVC (Model-View-Control)模式 (並非是廠商針對 Web 端提出的 Web MVC 技術),讓系統主結構 (業務邏輯/資料存取)有效隔離展示層與永續儲存機制的直接耦合 (coupling)。
微觀結構設計則是傳統物件導向所談及從領域概念模型 (domain conceptual model),導出到軟體物件與資料模型 (class/data model)。這裡使用的分析設計技能包括了運用 Peter Coad 的「交易模式 (Transaction Pattern)」與 GoF 四人幫的「設計模式 (Design Patterns)」。有別於古典OO 一開始就要求較完整的設計 (太過理想化),現今系統開發則更為務實-運用重構 (re-factoring)的技巧,持續逐漸地重整系統,效果即是簡潔易維護的程式碼 (clean code)。而伴隨著重構的一項必要機制與紀律就必然要求一開始就要撰寫單元測試程式碼 (unit test code)。
上述兩個構面是互補的。軟體主結構一開始就不會實作於特定的UI/資料庫端,以最純淨的 POCO/POJO (plain-old CLR/Java Object)物件來實作,如此才有機會得以實施後續的重構,而重構則取決於某一功能的複雜度與價值來評估,進而創造出系統整體的再利用價值。
本文著重於巨觀結構分層界定與實踐,藉以驗證巨觀結構 POC 的可行性。觀念說明利用 UML 設計圖表現巨觀分層結構;實作則各以 C#.NET 與 Java/Spring 實現一個極小的案例來貫穿整個系統的分層結構元素。
C#.NET 採以 ASP.NET Web MVC 與 E-F (Entity Framework)實作;Java/Spring 則採以 Spring Web MVC 與 傳統 JDBC (也可改 Hibernate Framework)實作。兩者會再佐以 UML 循序圖 (sequence diagram),來輔助解讀案例執行時物件之間的互動合作關係。
巨觀分層結構基本責任界定
把主要分層結構當成元件 (component)看待,以界定各元件主要的責任 (responsibility)。
展示層 (Presentation tier)
主要負責收集 (例如從表單)資料與展現所處理後的資訊 (information)。展示層千萬不要擔任問題領域 (problem domain)的控制邏輯 (control logic),以及資料存取 (data access)/業務邏輯 (business logic)的工作,那會是導致系統僵化難以維護的主因。
中間層 (Middleware tier)
接收來自展示層的資料處理要求 (request),以及回傳 (response)所處理後的資訊。中間層主要擔負問題領域的控制邏輯,以及資料存取/邏輯運算等核心領域議題,所以也可稱為「業務層 (business tier)」。
資料來源層 (Data Source tier)
資料來源層可能是永續儲存機制 (如關聯資料庫),或者為需要取得支援服務的外部系統。與展示層一樣的問題是,千萬不要撰寫業務邏輯於關聯資料庫內 (典型利用 stored-procedure),因為會被該特定資料庫給綁架,且因採程序導向所撰寫的業務邏輯會導致程序碼相當冗長難以閱讀維護,均是系統僵化的主因之一。
資料模型 (Data Model)
資料模型即為廠商所定義 Web MVC 框架中的「Model」,它是作為 展示層與中間層 各類物件之間所傳遞的資料型態 (參數、回傳值)。 資料模型的實作可為「資料傳遞傳遞物件 (DTO, Data Transfer Object)」,也就是以物件型態來組織資料 (只有 getter/setter 方法);也可以是 JSON 這類簡單的 XML 結構。DTO 較適用於系統內部物件之間的資料傳遞;JSON 則適用於異質系統之間 (如透過 HTTP)所傳遞的資料型態。
注意的是,Data Model 不強調共用,每一個系統功能有自己所屬的資料傳遞的自訂型態。再則它不存在與資料庫表格一對一的對應,只要能滿足表單所需的資料收集或展示的局部欄位資訊即可,未來在中間層就是會透過 O-R Mapping 機制 (如 E.F or Hibernate 框架)作資料模型與資料庫表格之間的轉換 (transform)。
巨觀分層結構內部主要元素
展示層 (Presentation tier)
展示層可以是不同類型的 UI 結構元素。諸如 Windows Form/Java Swing 這類 Standalone 的表單物件;Web 端的 ASP.NET Form/Java Spring JSF (Java Server Face) Page,或為 ASP.NET MVC/Java Spring MVC 強調 View 與 UI Control 分離的設計;或是 Web Service 提供 API 供外部系統/Mobile App 等的連結。
展示層比較像是系統的門面,或可比喻為高樓大廈建築的「室內設計/裝潢」這一構面。也正因為系統會提供各類不同門面 (不同 UI 類型的呈現)的展示,所以更是不應將系統的核心邏輯撰寫於此。
中間層 (Middleware tier)
這裡依據 Ivar Jacobson 在「Object Advantage」一書所揭露的三種分析類別來界定位於中間層各類物件的基本責任:
- 控制 (control)類別:
實現問題領域所分析的系統功能 (system function),如源自於使用案例 (Use Case),所對應的領域控制類別 (domain control class)。控制類別負責實現某一系統功能及步驟程序,並可以直覺對應至類別名稱與方法 (系統功能→控制類別名稱;步驟→方法)。領域控制類別對於實作技術人員較常稱之為「服務層 (service-tier)」,主要差別在於系統功能分析的精緻度,是以單一操作目的來界定 (使用案例即採此方法),或以功能模組/模組樹方式來分析。
領域控制類別強烈要求以 POCO/POJO (Plain-old CLR/Java Object)來實作,如此才不會被特定相關於 UI/資料庫連結/工具 等技術框架 "綁架"。它可說是建構系統的主幹,並且是系統分層中擔任「Facade」封裝物件的角色:封裝資料存取/邏輯運算,以及負責處理領域控制邏輯。
一個必須同時要求的原則:撰寫控制類別程式碼就必須同時為其撰寫單元測試程式碼 (unit test code)。
撰寫單元測試程式碼,未來才有機會得以對程式碼作重構 (refactoring),如此系統才能具延展性並隨時保持功能的正確性。
- 邊界 (boundary)類別:
主要擔任連接至外部 (資料庫/外部系統)的工作。例如 資料存取物件 (DAO, Data Access Object)實作連接至資料庫的具體連線細節,以達成將資料模型與資料庫表格間資料狀態的一致性;Adapter 物件則擔任連接外部系統的工作,並需要依循連線外部所規範的通訊協定與呼叫規格。邊界型物件的變動性很高,會因實作內容改變而改變,所以這類型物件只負責擔任連接與傳遞、轉型等工作,而不把業務邏輯實作在此類型的物件上。
每一個負責實現系統功能的控制類型物件,均有各自的邊界類型物件,彼此盡量不要共用這些邊界物件,這是實作技術人員最常犯的問題,把資料存取實作成共用的儲庫 (repository),如此很難抽換。
若多個控制類型物件想共用存取方法,那麼就為其設計共用的資料存取的介面 (interface),而不要直接連結至具體的 DAO 類型物件。
- 實體 (entity)類別:
實體物件又稱為企業物件 (business object),它其實才是傳統物件導向所談及源自問題領域所分析而來的物件模型。前述所提的「微觀結構設計」,即是談此這種類型物件的分析設計議題。實體物件是系統的核心根源,它與位於如關聯資料庫內的表格均是採以相同的手法來分析出領域模型 (domain model),但是兩者差別主要在有無更進一步分析物件的行為,讓每一種類型的實體物件行為更明確、責任更為單一,這才是傳統物件所期望的美好境界。
但實務上,實體物件反而不一定需要存在,它可以根據系統功能行為的複雜度來決定是否需要顆粒度更精緻 (fine grained)的實體物件來處理;反之業務邏輯並不複雜,其實可以先實現於控制類型的物件,而後若當處理與判斷邏輯越形複雜時,再施以重構的手段,並衍生設計出責任更單一的實體類型物件,以更能順應業務邏輯的變動。
GoF 四人幫的設計模式 (design pattern),其中關於 行為 (behavior)與結構 (structure)兩大類型所揭露的物件設計模式,即是針對實體物件這塊範疇作所謂更精確的「微觀結構」設計。另前述所提的「交易模式 (transaction pattern)」則可以對領域物件先作初步的分類 (人、事/時、地、物),然後再各自去延展關聯。
Enterprise MVC 的 POC,即是根據上述分層結構設計圖,採以各平台的實作技術來驗證。
後續的文章 (分兩篇),會針對 C#.NET 與 Java/Spring 各撰寫一個極小的案例,但有確實實作上述分層結構的每一種類的元素來藉此作為驗證的 POC。