# Domain領域業務層與ADM模式解說
PhalApi使用的是ADM分層模式,Domain是連接Api層與Model層的橋梁。
## 何為Api-Domain-Model模式?
在傳統Web框架中,慣用MVC模式。可以說,MVC模式是使用最為廣泛的模式,但同時也可能是誤解最多的模式。然而,接口服務這一領域,與傳統的Web應用所面向的領域和需要解決的問題不同,最為明顯的是接口服務領域中沒有View視圖。如果把MVC模式生搬硬套到接口服務領域,不但會產生更多對MVC模式的誤解,還不利于實際接口服務項目的開發和交付。
仔細深入地再思考一番,接口服務除了需要處理輸入和輸出,以及從持久化的存儲媒介中提取、保存、刪除、更新數據外,還有一個相當重要且不容忽視的任務——處理特定領域的業務規則。而這些規則的處理幾乎都是邏輯層面上對數據信息的加工、轉換、處理等操作,以滿足特定場景的業務需求。對于這些看不見,摸不著,聽不到的領域規則處理,卻具備著交付有價值的業務功能的使命,與此同時也是最為容易出現問題,產生線上故障,引發損失的危險區。所以,在接口服務過程中,我們應該把這些領域業務規則的處理,把這些受市場變化而頻繁變動的熱區,單獨封裝成一層,并配套完備的自動化測試體系,保證核心業務的穩定性。
基于以上考慮,在MVC模式的基礎上,我們去掉了View視圖層,添加了Domain領域業務層。從而涌現了Api-Domain-Model模式,簡稱ADM模式。
簡單來說,
+ **Api層** 稱為接口服務層,負責對客戶端的請求進行響應,處理接收客戶端傳遞的參數,進行高層決策并對領域業務層進行調度,最后將處理結果返回給客戶端。
+ **Domain層** 稱為領域業務層,負責對領域業務的規則處理,重點關注對數據的邏輯處理、轉換和加工,封裝并體現特定領域業務的規則。
+ **Model層** 稱為數據模型層,負責技術層面上對數據信息的提取、存儲、更新和刪除等操作,數據可來自內存,也可以來自持久化存儲媒介,甚至可以是來自外部第三方系統。
## 專注領域的Domain業務層
Domain領域業務層,主要關注的是領域業務規則的處理。在這一層,不應過多關注外界客戶端接口調用的簽名驗證、參數獲取、安全性等問題,也不應過多考慮數據從何而來、存放于何處,而是著重關注對領域業務數據的處理。
## ADM職責劃分與調用關系
傳統的接口開發,由于沒有很好的分層結構,而且熱衷于在一個文件里面完成絕大部分事情,最終導致了臃腫漫長的代碼,也就是通常所說的意大利面條式的代碼。
在PhalApi中,我們針對接口領域開發,提供了新的分層思想:Api-Domain-Model模式。即便這樣,如果項目在實際開發中,仍然使用原來的做法,縱使再好的接口開發框架,也還是會退化到原來的局面。
為了能讓大家更為明確Api接口層的職責所在,我們建議:
Api接口服務層應該做:
+ 應該:對用戶登錄態進行必要的檢測
+ 應該:控制業務場景的主流程,創建領域業務實例,并進行調用
+ 應該:進行必要的日記紀錄
+ 應該:返回接口結果
+ 應該:調度領域業務層
Api接口服務層不應該做:
+ 不應該:進行業務規則的處理或者計算
+ 不應該:關心數據是否使用緩存,或進行緩存相關的直接操作
+ 不應該:直接操作數據庫
+ 不應該:將多個接口合并在一起
Domain領域業務層應該做:
+ 應該:體現特定領域的業務規則
+ 應該:對數據進行邏輯上的處理
+ 應該:調度數據模型層或其他領域業務層
Domain領域業務層不應該做:
+ 不應該:直接實現數據的操作,如添加并實現緩存機制
Model數據模型層應該:
+ 應該:進行數據庫的操作
+ 應該:實現緩存機制
在明確了上面應該做的和不應該做的,并且也完成了接口的定義,還有驗收測序驅動開發的場景準備后,相信這時,即使是新手也可以編寫出高質量的接口代碼。因為他會受到約束,他知道他需要做什么,主要他按照限定的開發流程和約定稍加努力即可。
如果真的這樣,相信我們也就慢慢能體會到精益開發的樂趣。
至于調用關系,整體上講,應根據從Api接口層、Domain領域層再到Model數據源層的順序進行開發。
在開發過程中,需要注意不能**越層調用**也不能**逆向調用**,即不能Api調用Model。而應該是**上層調用下層,或者同層級調用**,也就是說,我們應該:
+ Api層調用Domain層
+ Domain層調用Domain層
+ Domain層調用Model層
+ Model層調用Model層
如果用一張圖來表示,則是:

為了更明確調用的關系,以下調用是**錯誤**的:
+ 錯誤的做法1:Api層直接調用Model層
+ 錯誤的做法2: Domain層調用Api層,也不應用將Api層對象傳遞給Domain層
+ 錯誤的做法3: Model層調用Domain層
#### 這樣的約定,便于我們形成統一的開發規范,降低學習維護成本。比如需要添加緩存,我們知道應該定位到Model層數據源進行擴展;若發現業務規則處理不當,則應該進入Domain層探其究竟;如果需要對接口的參數進行調整,即使是新手也知道應該找到對應的Api文件進行改動。