進擊的碼農(一) 領域驅動設計(DDD)落地實戰

2021-10-23 02:30:49 字數 3390 閱讀 3874

該層很簡單,作為與客戶端互動的入口, 通常只放controller,然後呼叫應用服務實現業務,**如下:

public class ordercontroller 

@apioperation("建立訂單")

public response createorder(@requestbody @valid createordercmd command)

@apioperation("修改訂單詳細位址")

public response changeaddressdetail(@pathvariable("orderid") string orderid, @requestbody @valid changeaddressdetailcmd command)

@apioperation("獲取訂單資訊")

public responsewithdatagetorder(@pathvariable("orderid") string orderid)

representation放的是返回給客戶端的查詢資料的封裝, 為啥要有這個呢, 因為查詢可能是非常複雜的(如根據距離從遠到近、並按銷量查詢商品等),這樣一些查詢就有可能不通過聚合根,而是由應用層直接呼叫repository來完成。

領域層根據包名和好理解。

converter:轉行器,把do(data object 資料物件,即資料庫對於的表)和dto進行轉換、實體和do進行轉換。

entity:實體,如聚合根、實體等。

event: 領域事件, 領域事件產生的時機為當聚合根的狀態改變時,如訂單已支付、訂單已取消等狀態改變時會產生領域事件。

factory:工廠方法, 很多用例都推崇使用工廠方法來建立聚合根, 但是也有缺陷,當聚合根的成員很多時, 構造方法引數很多, 這時候,建議通過建造者模式來建立聚合根。參看下面**。

repository:倉儲,即對聚合根進行儲存的介面, 同時我把實現類也放在這裡的原因是,如果實現類放在基礎設施層,那麼需要在基礎設施層依賴領域層進行物件的裝換。

representation:跟應用層一樣

service:領域服務,聚合根是業務邏輯的主要載體,也就是說業務邏輯的實現**應該盡量地放在聚合根或者聚合根的邊界之內。但有時,有些業務邏輯並不適合於放在聚合根上,如我們儲存訂單(order)的時候需要同時儲存訂單品相(order_item),涉及到兩個實體的操作,在這種迫不得已的情況下,那麼引入領域服務(domain service),盡量少用吧。

valuepbject: 值物件,如訂單(order)裡面的收貨位址(address),盡量少用值物件,除非你非常明確它就是值物件,否則建議都用實體,如果不合理,在**的演進過程中進行修改和完善。例如訂單(order)實體包括訂單品相(order_item)和收貨位址(address), 我設定order_item為實體、address為值物件的原因是order_item是需要單獨持久化到資料庫中。

public class order extends aggregateroot 

// public order(string id, address address, listitems, date createtime)

//// public order(string id, int totalprice, address address, listitems, date createtime, orderstatus orderstatus)

private order(builder builder)

// public static order create(string id, address address, listitems)

// public static order create(string id, address address, int totalprice, int status, listitems, date createtime)

public static class builder

if (null == orderstatus)

return new order(this);

}public builder setid(string id)

public builder setaddress(address address)

public builder setitems(listitems)

public builder setcreatetime(date createtime)

public builder setorderstatus(int status)

public builder settotalprice(integer totalprice)

private int calculatetotalprice(listitems)

}public void changeaddressdetail(string detail)

public string getid()

public int gettotalprice()

public address getaddress()

public listgetitems()

public date getcreatetime()

public orderstatus getorderstatus()

}

整個專案結構大致就這樣, 隨著對ddd的理解,專案結構可能會隨著時間而改變。由於筆者知識有限,不足和錯誤的地方,請大家隨便噴和指正。

talk is cheap , show me the code

領域驅動設計(DDD)筆記(一)

最近在看 領域驅動設計 這本書,準備寫點學習筆記博文記錄系列。記錄本書中的要點和疑惑,不定期更新!先放張marginnote的圖 每個aggregate都有乙個根 root 和乙個邊界 boundary 邊界定義了aggregate的內部都有什麼,根則是aggregate中所包含的乙個特定entit...

DDD 領域驅動設計 領域模型中的使用者設計

驗證 根據 userid 判斷此使用者是否擁有部落格。許可權 根據當前 loginname,判斷此使用者是否擁有審核許可權。public int userid public string userloginname public string userdisplayname public strin...

重新解讀DDD領域驅動設計 一

回顧 十年前,還未踏入某校時,便聽聞某學長一畢業就入職北京某公司,月薪過萬。對於乙個名不見經傳的小學院,一畢業能拿到這個薪水還是非常厲害的。聽聞他學生期間參與開發了一款 軟體,那時正迎來一波瘋漲。時也運也。我那時心裡就想,只會軟體也行不通吧,至少要熟悉 規則。在還未踏入程式設計大門時,我就清楚的認識...