新聞中心
本文轉(zhuǎn)載自微信公眾號「codeasy」,作者閻華 。轉(zhuǎn)載本文請聯(lián)系codeasy公眾號。

成都創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供建水網(wǎng)站建設(shè)、建水做網(wǎng)站、建水網(wǎng)站設(shè)計、建水網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、建水企業(yè)網(wǎng)站模板建站服務(wù),10年建水做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。
使用了DDD(領(lǐng)域驅(qū)動設(shè)計)后,代碼編寫有什么不一樣呢?這個系列文章會對一些優(yōu)秀的DDD實例代碼進(jìn)行分析,管中窺豹,略見數(shù)斑。這是第六篇,繼續(xù)以IDDD_Sample為例做分析。
防腐層不是PORT/ADAPTER
防腐層(ACL)是比較容易被開發(fā)人員接受的概念,是因為很多人會把遠(yuǎn)程調(diào)用的port/adapter理解成防腐層,雖然它們有一定的關(guān)系,但這種理解并不準(zhǔn)確。
防腐層講的不是技術(shù)實現(xiàn),它講的“知識”——雖然A上下文依賴B上下文的概念,但還是盡可能不要讓B上下文里的領(lǐng)域概念侵入到A上下文的領(lǐng)域?qū)?,否則,A就被B腐化了。
在IDDD_Sample中有三個限界上下文:
- 身份認(rèn)證上下文,這里的領(lǐng)域模型主要有“用戶”、“角色”等
- 協(xié)作上下文,這里的的領(lǐng)域模型主要有“論壇”、“帖子”、“日歷”、“討論”、“作者”等
- 敏捷管理上下文,這里的主要領(lǐng)域模型是和Scrum相關(guān)的概念,比如Sprint,ProductOwner,Backlog等
協(xié)作上下文和敏捷管理上下文都依賴于身份認(rèn)證上下文。
這里的關(guān)鍵點在于雖然依賴,但在協(xié)作上下文里有“作者”等概念,但沒有“用戶”這個概念,雖然它們有對應(yīng)關(guān)系;在敏捷管理上下文里,有“ProductOwner”、“TeamMember”等概念,但沒有“用戶”這個概念,雖然它們有對應(yīng)關(guān)系。
另外,“用戶”這個概念映射到敏捷管理上下文里,對應(yīng)的是多個實體;而映射到協(xié)作上下文里是多個值對象。下面我們分別來看一下。
實體到實體的映射
一個上下文里的實體在另一個上下文里體現(xiàn)為一個或多個實體,這是一種很常見的做法,有點兒像我們常見的“數(shù)據(jù)集成”。
在敏捷管理上下文里,有兩個實體,一個是 ProuctOwner ,一個是 TeamMember 。
在身份認(rèn)證上下文里,我們給一個用戶分配了 ScrumProductOwner 這個角色,會在敏捷管理上下文里生成一個 ProductOwner 實體;給一個用戶分配了 ScrumTeamMember 這個角色,會在敏捷管理上下文里生成一個 TeamMember 實體。
敏捷管理上下文監(jiān)聽了身份認(rèn)證上下文里用戶分配角色的事件,是通過agilepm.port.adapter.messaging.rabbitmq.RabbitMQTeamMemberEnablerListener這個監(jiān)聽實現(xiàn)的:
- @Override
- protected String[] listensTo() {
- return new String[] {
- "com.saasovation.identityaccess.domain.model.access.UserAssignedToRole"
- };
- }
處理邏輯如下:
- @Override
- protected void filteredDispatch(String aType, String aTextMessage) {
- NotificationReader reader = new NotificationReader(aTextMessage);
- String roleName = reader.eventStringValue("roleName");
- String username = reader.eventStringValue("username");
- String emailAddress = reader.eventStringValue("emailAddress");
- String firstName = reader.eventStringValue("firstName");
- ……
- if (roleName.equals("ScrumProductOwner")) {
- this.teamApplicationService().enableProductOwner(
- new EnableProductOwnerCommand(
- tenantId,
- username,
- firstName,
- lastName,
- emailAddress,
- occurredOn));
- }
- ……
事件監(jiān)聽器調(diào)用應(yīng)用服務(wù)生成了一個 ProductOwner ,在敏捷管理上下文的領(lǐng)域邏輯里,就只會理解 ProductOwner 這個概念,而不會理解用戶這個概念了。
實體到值對象的映射
有時候使用值對象比使用實體更經(jīng)濟(jì)。比如在協(xié)作上下文里,一篇帖子有作者的概念,但這個作者在只是一個值對象。
image.png
作者是一種類型的協(xié)作者,除了身份標(biāo)識,還有name、email等屬性。
但在創(chuàng)建一篇帖子時,傳給帖子創(chuàng)建服務(wù)的一個參數(shù)是 username ,但帖子上的Author 這個值對象是怎么構(gòu)建出來的呢?
這就需要調(diào)用身份認(rèn)證上下文的服務(wù)去獲取user更多的信息,來構(gòu)建 Author。但應(yīng)用層或領(lǐng)域?qū)硬荒苤苯尤フ{(diào)用一個RPC/REST服務(wù),這里定義了一個 CollaboratorService 接口,里面有一個 authorFrom 方法可以通過用戶名來創(chuàng)建一個 Author 的方法。在它實現(xiàn)類里,調(diào)用了 UserInRoleAdapter/HttpUserInRoleAdapter ,通過HTTP遠(yuǎn)程獲取了user的信息。這里要特別注意的是,CollaboratorService 和 Author 這個領(lǐng)域模型再同一個包下,即在 collaboration.domain.model.collaborator 這個包下。而其它的幾個類都在port/adapter 包下,即 collaboration.port.adapter.service 下面。
是的,你沒猜錯,這里用了IoC容器實現(xiàn)了依賴倒置
image.png
上下文集成的兩種技術(shù)手段
上面的兩種映射方式正好用到了技術(shù)上兩種常用的集成手段 —— 基于消息和基于API。但首先要記住的是防腐層是關(guān)于領(lǐng)域概念的防腐,不是關(guān)于技術(shù)的,雖然我們需要通過 port/adaper 這種技術(shù)實現(xiàn)來把應(yīng)用層/領(lǐng)域?qū)雍途唧w的實現(xiàn)技術(shù)做隔離,但防腐層不等于是port/adaper。
網(wǎng)站題目:防腐層防的是哪門子腐
文章分享:http://www.5511xx.com/article/dpccedj.html


咨詢
建站咨詢
