「Core J2EE Design Patterns 」一書,提出了許多實用的設計樣式(Patterns),以應用在 J2EE(尤其以 EJB 為核心)平台環境下的最佳實務與設計策略。
整本書將所揭露的樣式整理分類為三個階層(tiers):Presentation Tier、Business Tier、Integration Tier。
對應問題領域(Problem Domain)所建構的物件模型(Object Model),在 UML 是以類別圖(Class Diagram)來實作的,是位於 Business Tier 所稱之的 Business Object。而類別圖亦即為整個軟體系統的核心結構。結構分析與設計的好壞差別,會明顯反應在系統的效能與需求的變動管理上。
尤以後者,最重要的設計考量:如何將變動侷限在一小塊範圍之內。
為了達成此一目的,「低耦合性(loose coupling)」與「高內聚力(high cohesion)」是在設計的階段中,時常所需要觀照與調和的。
位於 Business Tier 內 Session Facade、Application Service 兩個樣式的揭露,即在於期望能達成上述「低耦合性」與「高內聚力」的設計考量。
我看了許多篇國外的文章與討論,發現到許多 Developer 並不是很瞭解這兩個樣式的目的與應用。其實仔細去觀察思考,這兩個樣式均旨在 "保護企業物件(Business Object)", 為了保護企業物件,所以需要能封裝(Encapsulate) 客戶(Client)端 直接對企業物件的存取。除了封裝的考量外,另外也需要有一個控制協調的角色,稱之為控制物件(Control Object)。來協調多個企業物件之間的互動合作。
所以,上述兩個樣式的設計應用,是誰負責封裝?、誰負責控制呢?
從該書的內容,許多讀者會以為 Session Facade 是負責封裝,Application Service 是負責控制協調。
其實,不然不然,兩者都可以是封裝的角色,也可以是控制者的角色。
而事實上,Session Facade、Application Service、Business Object 三者的關係是源自於 MVC (Model-View-Controller) 的設計模式。MVC 樣式的目的即在於解開不同類型物件(例如 UI 物件與企業物件)之間的糾結,增進系統的彈性與元件的再利用性。參考如下圖一。
圖一、MVC 設計模式的對應關係
若從另外一個角度來觀察時,Session Facade 是可以 "聚合(aggregiate)" 多個 Application Service,以組合併實現更為複雜的企業流程。此時,Session Facade 是擔任著主要控制協調者的角色,而 Applicatin Service,成為可以被 "共用(Share)" 的企業流程物件了。參考如下圖二。
圖二、SF、AS、BO 實作 Controller、CBPO、CBO 三個階層的關係
如此說來,為何要一分為二呢?是否可以把兩者的角色,即將封裝與控制邏輯合而為一呢? 是的,在設計上,這是可以考量的,例如,實現使用案例的控制物件,稱為 UCO (Use Case Control Object),可以同時擔任 Facade 與 Controller 的角色。
那麼,哪時候又會明顯地將 Facade 與 Controller 兩個角色分開呢?
在 J2EE 的設計樣式中,Session Facade 是以 EJB(Enterprise Java Bean)中的 Session Bean 來實作的,利用 Session Bean 實作的幾個特點:
- 封裝了內部的企業物件(無論是否是以 Entity Bean 或一般 Java Object 實作),而提供給外界的是一致性的服務 (Uniform Services)。
- 提供給客戶端遠端存取(Remote Access)的服務。這是 Session Bean 規格既有的優勢,可以實現遠端的溝通。
當我有以上的需求考量時,我會以 Stateful Session Bean 來實作 Session Facade 樣式。至於為何是設計為 "Stateful"? 主要的理由在於與客戶端的對話互動的過程的期間(Session),利用 "Stateful Session Bean" 來保存對話過程之間的狀態(State)情形。
至於 Application Service 樣式的應用,我是對應了在需求分析的階段中,對每一個使用案例,均設計了使用案例的控制物件(Use Case Control Object)。
例如, "Place Order"、"Purchase Order" 等使用案例,我會設計 "Place_Order_Controller"、"Purchase_Order_Controller" 的控制物件。對應至 J2EE Design Pattern 內,使用案例控制物件會定義成 "Application Service"。
至於在 J2EE 平台實作 Application Service 的物件,可以是 Session Bean,也可以是 JavaBean,或者以一般的 Java 物件來實作。若沒有特別的設計考量,例如大量交易處理的穩定與效能因素,我會直接以一般的 Java Object (該書將之稱為 POJOs, Plain Old Java Objests)來實作即可。
每一個使用案例,代表了一個業務流程—系統所提供的功能。而每一個業務流程,還可以因應需求而被動態組合來服務一個更大的功能。這也是對照上圖二所提及的,Application Service 是位於 "Common Business Process" 的層次,因為,每一個使用案例所代表的業務流程,是可以被再利用的。
例如,在訂購資訊的管理作業中,其中的一個使用案例 "查詢訂購資訊",同時也會被使用在出貨管理作業的使用案例 "出貨"。顯然,"查詢訂購資訊" 的使用案例會被使用在訂購管理與出貨管理的作業上—可以是一個獨立完整的使用案例;也可以被包含於(included)另一個使用案例內。
所以,在 J2EE 的設計考量,我會設計兩個 Session Facade 物件:訂購管理_Facade Session Bean 以及 出貨管理_Facade Session Bean。然後,如上所述,每一個使用案例的控制物件被設計成 Application Service 物件。
以上說明,可以瞭解到,在下述的兩種情況下, Session Facade 也可以被考量實作的:
- 可以聚合(aggregiate) 多個 Application Service 物件,以提供更鉅大的企業服務。
- 可以依業務性質或同質性的功能等考量,將一群使用案例,利用 Session Facade 群組(Grouping)起來。這是屬於一種顆粒度(-grained)的設計考量,避免以 Session Bean 實作每一個使用案例的控制物件 (屬於較精緻的顆粒度設計,finer-grained);而是將之群組起來,僅設計為一顆擔任 Session Facade 的 Session Bean (屬於粗的顆粒度設計,coarse-grained)。 ***註*** 太多的 Session Bean,會影響到關於系統的資源及效能等因素。
我利用了一個使用案例圖的實例,參考如下圖三, 說明實現(Realize) "Place Order" 這個使用案例,在 J2EE 平台的設計考量下時,Session Facade、Application Service、Business Object 三者的實作與互動的關係。參考如下圖四的循序圖。
圖三、線上商品訂購出貨系統的使用案例圖
Helllo Session Facade:
1. 在三層架構中,答案是 Yes.
2. Session Facade 與 Application Service 在實體的設計上,可以合而為一,而是否是簡單的查詢呼叫,簡而言之,在三層架構中,是有必要透過 Control layer 的傳遞。
3. 三層架構是否是強制,需由專案開發團隊(尤其是 Architect)來決定,若以我們所輔導的專案而言,那麼,是必然存在著 MVC 結構的。至於您所提,Client 的查詢是否與 Biz Process 有無關連,這會透過需求的分析與系統結構的責任分派來判定。
4. 第四個問題如同第二個的回答一樣,不過,我推測,您可能對 Ap Service 的定義與我個人所定義的不太一樣,先思考一個問題,AP Service 會被實現成 “Stateless” or “Statefule” 呢?
請教一下,是不是Facade使用所有的Business都需透過App Service層?
如果Facade提供一個很簡單的功能,可能只是查詢一個資料而已,
這個查詢邏輯在Business Obj可能只是一個簡單的method,
那還有透過App Service的必要嗎?
如果強制三層架構一定存在,
那可能系統會存在很多一行程式的App Service,
因為Client有很多查詢不同種類小資料的需求,
與整個Biz Process無太大關聯,或是說他只是整個Biz Process的一小塊。
如果Facade可以直接使用BizObj,
App Service真的就是Common Biz Process Obj,
App Service會負責一組的功能,而且只負責一組有意義的邏輯,
Facade可以串接有小組共用邏輯的App Service與單一動作的Biz Obj,
可是這樣的做法是否會破壞整個分層架構??
Hello 神來之筆:
我瞭解您的意思。
MVC 是一種相對關係,單以 Struts Framework 而言,它是在 Presentation Layer 實作了 MVC 機制,也就如您最後一行所提及的。
而我上圖二所討論的,則是在 Business tier 層的討論。Session Facade 這個角色,相對於 CBPO and CBO 物件而言,它成為了控制與協調這些物件的控制者角色。
而事實上,若你再觀察,Application Service 物件相對於 Business Object,它則成為了 Controller 的角色。
就這如同上述我所說明,MVC 是一種相對關係,而不是絕對關係。
例如 Struts 層,內部分層了 MVC,但,相對於在整個 J2EE 架構內,它又僅屬於J2EE 的 MVC 中,那個 “View” 的角色。
不知您的圖二的MVC對應出自哪
以struts而言
只有module會跟business tier的session facade耦合
controller單單做view和module的協調, 並不需要跟business tier耦合
一般web的MVC
view–controller–module
而stuts的MVC是取代J2EE pattern裡的presentaion 那一層