DDD領域驅動模型設計
背景
使用DDD開發大概也有五個月的時間了,由於當時公司導師的推薦,第一次接觸DDD領域驅動到現在徹底迷戀這種開發的模式,為其思想的奧妙所折服,一直以來,總想花一點時間來總結一下,正直光棍節(天貓狂歡購物節)當天,“靜下心來”(PS:沒有人民幣)總結一下。
第一次接觸,就是這篇文章,當時看起來晦澀難懂,後來慢慢的讀起來,每一次都有精神的提升,網上也有很多關於DDD的介紹,這裡將不會在介紹概念什麼的,下邊主要是自己工作過程中的一些總結。
如何快速入門
第一次接觸DDD的時候,概念高深莫測,奧祕深不可見,大有不知所云的趨勢,後來導師的引導,讓直接從專案中直接入手,遂逐步揭開其一層層霧紗,如圖1:
DDD一般的分層結構和呼叫順序如上所述,infrastructure是基礎設施層,domain是領域層,application是應用層,facade和facade-impl是門面層(前者是門面介面層,後者是門面實現層),webapp是使用者介面層(採用web形式)。
下邊是一種專案的分層圖,採用的Maven管理程式碼。圖2:
分層的介紹
1、web:首先包含網站前端,如果使用SpringMVC的話,還需要其Controler,
該Controler層主要是用於接收HTTP請求和返回客戶端,一般不進行邏輯上的判斷,其代表了使用者可以進行的操作,一般不涉及領域驅動的思想,示例程式碼:
@ResponseBody
@RequestMapping(value = "/create", method = RequestMethod.POST)
public String create(AirlineWhiteListDTO airlineWhiteListDTO) {
MDC.put(ConstString.TRACE_ID, LogUtil.getTraceId(ConstAirlineWhiteList.CREATE));
Response response = airlineWhiteListFacade.create(airlineWhiteListDTO);
return super.handleResponse(response);
}
第一行使用MDC用於記錄(打log)http請求的順序和呼叫的方法,第二行呼叫“門面層”facede,獲得Response返回物件,第三行用於判斷是返回介面還是返回data等操作,即時SpringMVC的ModalAndView;
2、facade和facade-impl一個是門面層介面一個是門面層介面的實現類,示例程式碼:
@Autowired
IAirlineWhiteListApplication airlineWhiteListApplication;
public Response create(AirlineWhiteListDTO airlineWhiteListDTO) {
Response response = new Response();
try {
AirlineWhiteList airlineWhiteList = AirlineWhiteListAssembler.toEntity(airlineWhiteListDTO);
airlineWhiteListApplication.create(airlineWhiteList);
} catch (Exception e) {
response = new Response(e);
}
return response;
}
可以看出這是在web的controller中訪問的方法,主要進行資料的組裝(實體物件和資料傳輸物件的轉換),以及返回物件Response的轉換。
之所以成為門面層,我們暫可認為是我們使用者可以看到的整個系統的東西,例如上述中的Response就是返回給使用者看的東西。
3、Application層,上述的facade呼叫到了application中的方法,
@Inject
private AirlineWhiteList airlineWhiteList;
public boolean create(AirlineWhiteList airlineWhiteList) {
return this.airlineWhiteList.add(airlineWhiteList);
}
這一層主要是操作實體物件的,是於資料更近一層的操作,主要定義了使用者所擁有的方法和屬性,操作實體物件層,將實體物件所有的方法展示出來供使用者使用;
4、domain層,資料實體層,相比MVC中的modal簡單的只是資料庫的對映,這種“毫無靈魂”的物件,領域模型中不但有一個實體物件的屬性還有其方法,(我們可以在實際使用的時候使用繼承DTO的方式),在這一層中定義了實體物件操作資料庫的方法;
這裡我們的實體物件不僅是擁有屬性還具有方法的,就像一個人一樣,我們不但擁有做人的基本特徵(兩手、兩腳等),我們還有屬於自己的技能(方法),這樣的話才是一個擁有靈魂的東西;
5、infra這一層包含了訪問資料庫的方法、資料倉儲(sql、nosql、api)和一些工具類,service等;
由於是domain層呼叫該層的,實體物件的操作固然包含CRUD,既是我們需要進行對資料庫的操作,當我們只有一個數據源的時候,很簡單,但是後期專案中資料來源可能會增加,可能會新增快取等,這樣的話使用原來的MVC模式的話,我們可能需要修改很多,如下圖:
但是使用DDD的話,由於我們的Domain呼叫的是infra 資料倉庫Repository介面,Repository中定義了訪問資料來源的方法,這樣的話,當我門新增資料來源的時候,我們的Domain層以上都無需修改,只需進行infra層的修改即可。
上圖中有2個數據源,一個是sql一個是nosql,在方框中的Repository即呼叫的是nosql和sql中的方法,這樣的話Domain直接呼叫Repository即可。
領域驅動的示例:
如果想快速的領回DDD的奧妙,這裡有一個案例,一個很不錯的開源系統,使用的正是DDD思想,可以把程式碼下載下來仔細研究,其中的思想是很不錯、很不錯的,地址如下:http://www.openkoala.org/
總結:
類比MVC“啞鈴式”的分層結構中,Model和View程式碼少,Controller程式碼臃腫的佈局格式,DDD擁有更多的分層,各層之間各司其職,協調工作,一步步呼叫,井然有序,對於後期的維護,只要是熟悉DDD的開發人員都可以很好的維護。