介紹
一個應用的代碼庫的分層是一個廣為接受的技術,用來減少復雜度和提高代碼復用性。ABP依照DDD理念來分層,在DDD裡有4個基本的層:
也可以根據需要添加層,例如:
這些都是以領域為核心的架構的通用層。實現上可能有些細微的差別。
ABP架構
層和結構的概覽如下:
下圖為一個包含5個項目的簡單分層應用:
一個層可以實現成一個或多個程序集。在大型項目裡可能為第三方依賴創建多個程序集更合適(像此處的EntityFramework),使每個層都有它自己的Context。
領域(Core)層
領域層必須實現所有業務規則。
實體:展示數據和領域業務的操作。通常地它們映射到數據庫表。
倉儲:類似於對象集合,用來獲取和持久化實體到數據源(數據庫)。領域層定義了倉儲,但不實現它們,由基礎層來實現它們。
領域事件:定義領域裡特定的事件,並觸發和處理它們。領域服務利用實體(及其它領域對象)實現那些不屬於某個單獨實體的業務規則。
工作單元:是一個管理數據庫連接和事務的設計模式,跟蹤實體變化並保存變化到數據存儲。領域層定義了它,但由基礎層實現它。
這一層應該盡可能地獨立於第三方類庫。
應用層
應用層包含用於展示層的應用服務。一個應用服務方法可以接收一個DTO(數據傳輸對象)作為輸入,使用這個輸入執行一些領域層的操作,並在需要時返回另一個DTO。它不應該接收或返回實體。一個應用服務方法被認為是一個工作單元。用戶輸入驗證也是在這一層實現。建議使用類似於AutoMapper庫等工具來映射實體和DTO。這層還包含當前用戶信息的會話(Session)。
基礎層
當領域層定義倉儲、工作單元、和其它服務接口後,基礎層實現這些商品。用ORM工具(如NHibernate或EntityFramework)實現倉儲。ABP已經這此二種ORM框架提供基類。基礎層從其它層抽象出對第三方庫的依賴。在這層裡也可以使用數據遷移。
除了數據訪問,我們可能需要為服務供應商進行抽象,例如,我可能使用服務供應商提供的服務發送短訊,我們可以在領域層或應用層定義一個接口來抽象它,然後我們在這層裡實現它。
Web & 展示層
Web層用Asp.net、Web API和Asp.net Core實現。兩種方式都可在單頁面應用(SPA)或多頁面應用(MPA)中實現,啟動模板也都支持這兩種方式。
在一個SPA裡所有資源只加載一次(或預先加載核心資源然後在有需要時延遲加載其它資源)給客戶端(浏覽器),後續的與服務器的交互使用AJAX調用,從服務端獲取數據後,Html代碼在客戶端創建。整個頁面不再刷新,視圖只是在需要時換出換入。現在有很多Javascript SPA框架,例如Angularjs,Backbonejs和Emberjs。ABP可以使用任何一種,但使用示例和一些幫助機制可能使用Angular更容易。
在一個MPA裡,客戶端發送一個請求到服務端,服務端代碼(通常是Asp.net MVC控制器)從數據庫獲取數據,並Razor渲染視圖創建HTML。創建之後的頁面被發送回客戶端顯示。每個新頁面會刷新整個頁面。不過客戶端也可以通過額外的AJAX請求來優化體驗。
SPA和MPA涉及到完全不同的結構。一個管理面板的完美選擇是SPA,另外方面,一個博客最好選擇MPA,因為它更有利於被搜索引擎發現。即便如此,SPA也可以通過工具使得被搜索引擎發現。當然這些都只是通常做法。
SignalR是一個從服務端推送通知給客戶端的完美工具。它能給用戶帶來豐富、實時的體驗。
當下在客戶端有許多Javascript類和框架。Jquery是最流行並擁有成千的免費插件。當然還有很多工具/框架使得它與HTML和CSS更好地合作。例如,推特的Bootstrap就是一個非常流行的HTML/CSS框架。
ABP提供基礎服務,從你的應用服務自動創建一個Web API層,Javascript可以很容易地使用它們。另外,它提供基礎服務來管理應用菜單、本地化和語言切換。同時包含一個簡單但統一的Javascript API來簡化系統信息和通知的顯示。
ABP在服務端自動處理異常並返回一個對應的響應給客戶端。
其它
ABP使用Castle Windsor框架支持依賴注入。同時使用Log4Net為客戶端記錄日志,然而,可以很方便地切換日志類庫,只是利用Castle的抽象日志基礎,而不需要改變代碼。
總結
ABP協調一些最好的框架/類庫與它自身的類和系統來提供一個更好的基礎服務,方便使用多層結構創建一個Web應用。同時提供的模板更容易地為你的應用提供多層解決方案。