在引入實例以前,我們有必要回顧,並進一步了解分層架構。“層”是一種體系結構模式[POSA1],也是被廣大軟件從業人員用得最為廣泛而且最為靈活的模式之一。記得在CSDN上,時常有朋友問到:“分層是什麼?為什麼要分層?三層架構是不是就是表現層、業務邏輯層和數據訪問層?”
到這裡,你可能會覺得這些朋友的問題很簡單,分層嘛,不就是將具有不同職責的組件分離開來,組成一套層內部高聚合,層與層之間低耦合的軟件系統嗎?不錯!這是分層的目標。但是,我們應該如何分層呢?
領域驅動設計的討論同樣也是建立在層模式的基礎上的,但與傳統的分層架構相比,它更注重領域架構和技術架構的分離。
傳統的三層架構
如上文那位朋友提的問題那樣,最簡單的分層方式自然就是“表現層、業務邏輯層和數據訪問層”,我們可以用下圖來表示這個思想:
注意圖中打虛線的“基礎結構層”,從實踐的表現上來看,這部分內容可能就是一些幫助類,比如 SQLHelper之類的,也可能是一些工具類,比如TextUtility之類。這些東西可以被其它各層所訪問。而基於分層的概念,表現層只能跟業務邏輯層打交道,而業務邏輯層在數據持久化方面的操作,則依賴於數據訪問層。表現層對數據訪問層的內容一無所知。
從領域驅動的角度看,這種分層的方式有一定的弊端。首先,為各個層面提供服務的“基礎結構層”的職責比較紊亂,它可以是純粹的技術框架,也可以包含或處理一定的業務邏輯,這樣一來,業務邏輯層與“基礎結構層”之間就會存在依賴關系;其次,這種結構過分地突出了“數據訪問”的地位,把“數據訪問”與 “業務邏輯”放在了等同的地位,這也難怪很多軟件人員一上來就問:“我的數據表該如何設計?”
領域驅動設計的分層
領域驅動設計將軟件系統分為四層:基礎結構層、領域層、應用層和表現層。與上述的三層相比,數據訪問層已經不在了,它被移到基礎結構層了。
基礎結構層:該層專為其它各層提供技術框架支持。注意,這部分內容不會涉及任何業務知識。眾所周知的數據訪問的內容,也被放在了該層當中,因為數據的讀寫是業務無關的
領域層:包含了業務所涉及的領域對象(實體、值對象)、領域服務以及它們之間的關系。這部分內容的具體表現形式就是領域模型(Domain Model)。領域驅動設計提倡富領域模型,即盡量將業務邏輯歸屬到領域對象上,實在無法歸屬的部分則以領域服務的形式進行定義。有關領域對象和領域服務的內容,我會在接下來的案例中進行闡述
應用層:該層不包含任何領域邏輯,但它會對任務進行協調,並可以維護應用程序的狀態,因此,它更注重流程性的東西。在某些領域驅動設計的實踐中,也會將其稱為“工作流層”。應用層是領域驅動中最有爭議的一個層次,也會有很多人對其職責感到模糊不清。比如,有些國外的開發人員會覺得,既然不包含領域邏輯,那又如何協調工作任務呢?我會在《應用層與實體事件》章節對這些問題進行探討
表現層:這個好理解,跟三層裡的表現層意思差不多,但請注意,“Web服務”雖然是服務,但它是表現層的東西
從上圖還可以看到,表現層與應用層之間是通過數據傳輸對象(DTO)進行交互的,數據傳輸對象是沒有行為的POCO對象,它的目的只是為了對領域對象進行數據封裝,實現層與層之間的數據傳遞。為何不能直接將領域對象用於數據傳遞?因為領域對象更注重領域,而DTO更注重數據。不僅如此,由於“富領域模型”的特點,這樣做會直接將領域對象的行為暴露給表現層。
從下一個章節開始,我將以最簡單的銷售系統為例,介紹EntityFramework下領域驅動設計的應用。