日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
領(lǐng)域驅(qū)動(dòng)編程,代碼怎么寫(xiě)?

一、前言

加入阿里健康之后,我所在的團(tuán)隊(duì)也在積極推進(jìn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的應(yīng)用,相關(guān)同學(xué)也曾給出優(yōu)秀的腳手架代碼,但目前看起來(lái)落地情況并不太理想,個(gè)人淺見(jiàn),造成這種結(jié)果主要有四個(gè)原因。

成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供黃龍網(wǎng)站建設(shè)、黃龍做網(wǎng)站、黃龍網(wǎng)站設(shè)計(jì)、黃龍網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、黃龍企業(yè)網(wǎng)站模板建站服務(wù),十載黃龍做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

  • 大家更熟悉 MVC 的編程模式,需要快速實(shí)現(xiàn)某個(gè)功能的時(shí)候,往往傾向于使用較為穩(wěn)妥、熟悉的方式。
  • 大家對(duì)領(lǐng)域驅(qū)動(dòng)編程應(yīng)該怎么編寫(xiě)并沒(méi)有一個(gè)統(tǒng)一的認(rèn)知(Axon Framework[1] 對(duì)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)實(shí)現(xiàn)的非常好,但它太“重”了)。
  • DDD 落地本身就比較難,往往需要事件驅(qū)動(dòng)和 Event Store 來(lái)完美實(shí)現(xiàn),而這二者是我們不常用的。
  • 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)是面向復(fù)雜系統(tǒng)的,業(yè)務(wù)發(fā)展初期看上去都比較簡(jiǎn)單,一上來(lái)就搞領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)有過(guò)度設(shè)計(jì)之嫌。這也是領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)常常在系統(tǒng)不得不重構(gòu)的是時(shí)候才被拿出來(lái)討論的原因。

筆者曾在研發(fā)過(guò)程中研究、實(shí)踐過(guò)領(lǐng)域驅(qū)動(dòng)編程,對(duì)領(lǐng)域驅(qū)動(dòng)框架 Axon Framework 也做了深入的了解,(也許是因?yàn)闃I(yè)務(wù)場(chǎng)景相對(duì)簡(jiǎn)單)當(dāng)時(shí)落地效果還不錯(cuò)。拋卻架構(gòu)師的視角,從一線研發(fā)同學(xué)的角度來(lái)看,基于領(lǐng)域驅(qū)動(dòng)編程的核心優(yōu)勢(shì)在于:

  • 實(shí)施面向?qū)ο蟮木幊棠J剑M(jìn)而實(shí)現(xiàn)高內(nèi)聚、低耦合。
  • 在復(fù)雜業(yè)務(wù)系統(tǒng)的迭代過(guò)程中,保證代碼結(jié)構(gòu)不會(huì)無(wú)限制地變得混亂,因此保證系統(tǒng)可持續(xù)維護(hù)。

領(lǐng)域驅(qū)動(dòng)開(kāi)發(fā)最重要的當(dāng)然是正確地進(jìn)行領(lǐng)域拆解,這個(gè)拆解工作可以在理論的指導(dǎo)下,結(jié)合設(shè)計(jì)者對(duì)業(yè)務(wù)的深入分析和充分理解進(jìn)行。本文假定開(kāi)發(fā)前已經(jīng)進(jìn)行了領(lǐng)域劃分,側(cè)重于研究編碼階段具體如何實(shí)踐才能體現(xiàn)領(lǐng)域驅(qū)動(dòng)的優(yōu)勢(shì)。

二、保險(xiǎn)領(lǐng)域知識(shí)簡(jiǎn)介

以保險(xiǎn)業(yè)務(wù)為例來(lái)進(jìn)行編程實(shí)踐,一個(gè)高度抽象的保險(xiǎn)領(lǐng)域劃分如圖所示。通過(guò)用例分析,我們把整個(gè)業(yè)務(wù)劃分成產(chǎn)品域、承保、核保、理賠等多個(gè)領(lǐng)域(Bounded-Context),每個(gè)領(lǐng)域又可以根據(jù)業(yè)務(wù)發(fā)展情況拆分子域。當(dāng)然,完備保險(xiǎn)業(yè)務(wù)要比圖中展現(xiàn)的復(fù)雜太多,這里我們不作為業(yè)務(wù)知識(shí)介紹的篇章,只是為了方便后續(xù)的代碼實(shí)踐。

三、領(lǐng)域驅(qū)動(dòng)開(kāi)發(fā)的代碼結(jié)構(gòu)

1. 領(lǐng)域驅(qū)動(dòng)的代碼分層

可以使用不同的 Java 項(xiàng)目發(fā)布不同的微服務(wù)對(duì)領(lǐng)域進(jìn)行隔離,也可以在同一個(gè) Java 項(xiàng)目中,使用不同 module 進(jìn)行領(lǐng)域隔離。這里我們使用 module 進(jìn)行領(lǐng)域隔離的實(shí)現(xiàn)。但是無(wú)論采用何種方式進(jìn)行領(lǐng)域隔離,領(lǐng)域之間的交互只能使用對(duì)方的二方包或者 API 層提供的 HTTP 服務(wù),而不能直接引入其他領(lǐng)域的其他服務(wù)。

在每個(gè)領(lǐng)域內(nèi)部,相對(duì)于 MVC 對(duì)應(yīng)用三層架構(gòu)的拆分,領(lǐng)域驅(qū)動(dòng)的設(shè)計(jì)將應(yīng)用模塊內(nèi)部分為如圖示的四層。

(1) 用戶接口層

負(fù)責(zé)直接面向外部用戶或者系統(tǒng),接收外部輸入,并返回結(jié)果,例如二方包的實(shí)現(xiàn)類、Spring MVC 中的 Controller、特定的數(shù)據(jù)視圖轉(zhuǎn)換器等通常位于該層。在代碼層面常常使用的包命名可以是 interface, api, facade 等。用戶接口層的入?yún)?、出參類定義采用 POJO 風(fēng)格。

用戶接口層是輕的一層,不含業(yè)務(wù)邏輯。安全認(rèn)證,簡(jiǎn)單的入?yún)⑿r?yàn)(例如使用 @Valid 注解),訪問(wèn)日志記錄,統(tǒng)一的異常處理邏輯,統(tǒng)一返回值封裝應(yīng)當(dāng)在這層完成。

用戶接口層所需要的功能實(shí)現(xiàn)是由應(yīng)用層完成,這里一般不需要進(jìn)行依賴倒置。編碼時(shí),該層可以直接引入應(yīng)用層中定義的接口,因而該層依賴應(yīng)用層。需要注意的是,雖然理論上用戶接口層可以直接使用領(lǐng)域?qū)雍突A(chǔ)設(shè)施層的能力,但這里建議大家在對(duì)這種用法熟練掌握前,最好采用嚴(yán)格的分層架構(gòu),即當(dāng)前層只依賴其下方相鄰的一層。

(2) 應(yīng)用層

應(yīng)用層具體實(shí)現(xiàn)接口層中需要功能,但該層并不實(shí)現(xiàn)真正的業(yè)務(wù)規(guī)則,而是根據(jù)實(shí)際的 use case 來(lái)協(xié)調(diào)調(diào)用領(lǐng)域?qū)犹峁┑哪芰Α?/p>

消息發(fā)送、事件監(jiān)聽(tīng)、事務(wù)控制等建議在這一層實(shí)現(xiàn)。在代碼層面常常使用的包命名可以是 application, service, manager 等。它用來(lái)取代 Spring MVC 中 service 層,并把業(yè)務(wù)邏輯轉(zhuǎn)移到領(lǐng)域?qū)印?/p>

(3) 領(lǐng)域?qū)?/h4>

領(lǐng)域?qū)用嫦驅(qū)ο蟮?,它主要用?lái)體現(xiàn)和實(shí)現(xiàn)領(lǐng)域里的對(duì)象所具備的固有能力。因此,在領(lǐng)域驅(qū)動(dòng)編程中,領(lǐng)域?qū)拥木幊虒?shí)現(xiàn)是不允許依賴其他外部對(duì)象的,領(lǐng)域?qū)拥木幊淌窃谖覀儗?duì)領(lǐng)域內(nèi)的對(duì)象所具備的固有能力和它要在當(dāng)前業(yè)務(wù)場(chǎng)景下展現(xiàn)什么樣的能力有一定了解后,可以直接編碼實(shí)現(xiàn)的。

例如我們最開(kāi)始接觸面向?qū)ο蟮木幊痰臅r(shí)候,常常會(huì)遇到的一個(gè)例子是鳥(niǎo)會(huì)飛、狗會(huì)游泳,假設(shè)我們的業(yè)務(wù)域只關(guān)心這些對(duì)象的運(yùn)動(dòng),我們可以做如下的實(shí)現(xiàn)。

public interface Moveable {
void move();
}
public abstract class Animal implements Moveable {}

public class Bird extends Animal {
public void move(){
//try to fly
System.out.println("I'am flying");
}
}
public class Dog extends Animal {
public void move(){
//try to swim
System.out.println("I'am swimming");
}
}

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

基于領(lǐng)域驅(qū)動(dòng)的編程需要這樣(充血模型)去實(shí)現(xiàn)對(duì)象的能力,而不是像我們?cè)?MVC 架構(gòu)中常常使用貧血模型,把業(yè)務(wù)邏輯寫(xiě)在 service 中。

當(dāng)然,即使采用了這樣的編程方式,距離實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)還差的遠(yuǎn),一些看似簡(jiǎn)單的問(wèn)題就可能給我們帶來(lái)巨大的不安感。例如復(fù)雜的對(duì)象應(yīng)當(dāng)如何初始化和持久化?同樣一個(gè)事物在不同領(lǐng)域都存在,但其關(guān)注點(diǎn)不同時(shí)這個(gè)事物應(yīng)當(dāng)分別怎么抽象?不同領(lǐng)域的對(duì)象需要對(duì)方的信息時(shí),應(yīng)當(dāng)怎么獲取?

這些問(wèn)題,我們也會(huì)在代碼示例部分嘗試給出一些參考的方案。

(4) 基礎(chǔ)設(shè)施層

基礎(chǔ)設(shè)施層為上面各層提供通用的技術(shù)能力,例如監(jiān)聽(tīng)、發(fā)送消息的能力,數(shù)據(jù)庫(kù)/緩存/NoSQL數(shù)據(jù)庫(kù)/文件系統(tǒng)等倉(cāng)儲(chǔ)的 CRUD 能力等。

2. 小結(jié)

根據(jù)對(duì)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)各層的進(jìn)一步分析,一個(gè)更加具體化的分層結(jié)構(gòu)如下。

基于上面的分層原則,前述保險(xiǎn)領(lǐng)域一個(gè)可以參考的代碼結(jié)構(gòu)如下,我們將在下面編碼示例詳細(xì)講解每一個(gè)分包的理念和作用。

四、領(lǐng)域驅(qū)動(dòng)開(kāi)發(fā)的代碼

理論上,DOMAIN 不依賴其他層次且是業(yè)務(wù)核心,我們應(yīng)當(dāng)先編寫(xiě)領(lǐng)域?qū)哟a,但是一則由于我們對(duì)保險(xiǎn)領(lǐng)域知識(shí)的欠缺,可能不清楚保單到底有哪些固有能力;二則為了便于講解,因此我們直接借助一個(gè)用例來(lái)展示代碼。

1. 用例

  • 用戶在前端頁(yè)面選擇保險(xiǎn)產(chǎn)品,選擇可選的保障責(zé)任,輸入投/被保人信息,選擇支付方式(分期/躉交等)并支付后提交投保請(qǐng)求;
  • 服務(wù)端接受投保請(qǐng)求 -> 核保 -> 出單 -> 下發(fā)保單權(quán)益。

這里用例 1 是用例 2 的前置用例,我們假定用例 1 已經(jīng)順利完成(用例 1 中完成了費(fèi)率計(jì)算),只來(lái)實(shí)現(xiàn)用例 2,并且用例 2 也只是大略的實(shí)現(xiàn),只要能把代碼樣式展示即可。

2. 用戶接口層編程實(shí)踐

(1) 分包結(jié)構(gòu)

其中 client 是對(duì) inusurance-client (公共二方包) 部分的實(shí)現(xiàn),web 是 rest 風(fēng)格接口的實(shí)現(xiàn)。

(2) 用例代碼

@AllArgsConstructor
@RestController
@RequestMapping("/insure")
public class PolicyController {
private final InsuranceInsureService insuranceInsureService;

/**
* 投保出單
* @param request
* @return 保單 ID
*/
@RequestMapping(value = "/issue-policy", method = RequestMethod.POST)
public String issuePolicy(IssuePolicyRequest request){
return insuranceInsureService.issuePolicy(request);
}
}

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.

這里用到的入?yún)⒑头祷刂档念惗荚趹?yīng)用層中定義。

3. 應(yīng)用層編程實(shí)踐

(1) 分包結(jié)構(gòu)

  • 其中最外層接口是面向具體業(yè)務(wù)場(chǎng)景的,可以根據(jù)業(yè)務(wù)發(fā)展再進(jìn)行分包。
  • pojo 包中定義了應(yīng)用層用到的各種數(shù)據(jù)類(上面的 IssuePolicyRequest 就在這里)及其向其他層傳播時(shí)需要進(jìn)行類型轉(zhuǎn)換的轉(zhuǎn)化器。
  • tasks 包中定義了一些定時(shí)任務(wù)的入口。

注意,在領(lǐng)域編程實(shí)踐中,會(huì)需要非常多的類型轉(zhuǎn)換,我們可以借助一些框架(例如 MapStruct[2])來(lái)減少這些類型轉(zhuǎn)換給我們帶來(lái)的繁瑣工作。

(2) 用例代碼:

@Service
@AllArgsConstructor
public class InsuranceInsureServiceImpl implements InsuranceInsureService {
private final PolicyFactory policyFactory;
private final StakeHolderConvertor stakeHolderConvertor;
private final PolicyService policyService;

/**
* 事務(wù)控制一般在應(yīng)用層
* 但是需要注意底層存儲(chǔ)對(duì)事務(wù)的支持特性
* 底層是分庫(kù)分表時(shí),可能需要其他手段來(lái)保證事務(wù),或者將非核心的操作從事務(wù)中剝離(例如數(shù)據(jù)庫(kù) ID 生成)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public String issuePolicy(IssuePolicyRequest request) {
Policy policy = policyFactory.createPolicy(request.getProductId(),
stakeHolderConvertor.convert(request.getStakeHolders()));

//出單流程控制
policyService.issue(policy);

PolicyIssuedMessage message = new PolicyIssuedMessage();
message.setPolicyId(policy.getId());
MQPublisher.publish(MQConstants.INSURANCE_TOPIC, MQConstants.POLICY_ISSUED_TAG, message);

return policy.getId().toString();
}
}

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.

這里代碼展示的是應(yīng)用層對(duì)用例 2 的處理:

  • 使用領(lǐng)域?qū)拥墓S類構(gòu)建 Policy 聚合。如果需要傳遞復(fù)雜對(duì)象,需要先用類型轉(zhuǎn)換器將應(yīng)用層的數(shù)據(jù)類轉(zhuǎn)化為領(lǐng)域?qū)拥膶?shí)體類或者值對(duì)象。
  • 使用領(lǐng)域?qū)臃?wù)控制出單流程
  • 發(fā)送出單成功消息,其他領(lǐng)域監(jiān)聽(tīng)到感興趣的消息會(huì)進(jìn)行響應(yīng)。

4. 領(lǐng)域?qū)泳幊虒?shí)踐

(1) 分包結(jié)構(gòu)

這里領(lǐng)域?qū)右还灿形鍌€(gè)一級(jí)分包:

  • anticorruption 是領(lǐng)域防腐層,是當(dāng)前領(lǐng)域需要獲知其他領(lǐng)域或者外部信息時(shí),對(duì)其他領(lǐng)域二方包的封裝。防腐層從代碼層面來(lái)看,可以避免調(diào)用外部客戶端時(shí),在領(lǐng)域內(nèi)部進(jìn)行復(fù)雜的參數(shù)拼裝和結(jié)果的轉(zhuǎn)換。
  • factory 解決了復(fù)雜聚合的初始化問(wèn)題。我們?cè)O(shè)計(jì)好領(lǐng)域模型供外部調(diào)用,但如果外部也必須使用如何裝配這個(gè)對(duì)象,則必須知道對(duì)象的內(nèi)部結(jié)構(gòu)。對(duì)調(diào)用方開(kāi)發(fā)來(lái)說(shuō)這是很不友好的。其次,復(fù)雜對(duì)象或者聚合當(dāng)中的領(lǐng)域知識(shí)(業(yè)務(wù)規(guī)則)需要得到滿足,如果讓外部自己裝配復(fù)雜對(duì)象或聚合的話,就會(huì)將領(lǐng)域知識(shí)泄露到調(diào)用方代碼中去。需要注意的是,這里主要是把聚合或?qū)嶓w需要的數(shù)據(jù)填充進(jìn)來(lái),而不涉及對(duì)象的行為。

因此這里工廠的核心作用是從各處拉取初始化聚合或?qū)嶓w所需要的外部數(shù)據(jù):

@Service
@AllArgsConstructor
public class PolicyFactory {
/**
* 產(chǎn)品領(lǐng)域防腐層服務(wù)
*/
private final ProductService productService;

/**
* 從各種數(shù)據(jù)來(lái)源查詢直接能查到的前置數(shù)據(jù),填充到 policy 中
* @param productId
* @param stakeHolders
* @return
*/
public Policy createPolicy(Long productId, List stakeHolders) {
PolicyProduct product = productService.getById(productId);
//其他填充數(shù)據(jù),這里調(diào)用了聚合自身的靜態(tài)工廠方法
Policy policy = Policy.create(product, stakeHolders);
return policy;
}
}

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.
  • model 中是領(lǐng)域?qū)ο蟮亩x。其中 vo 包中定義了領(lǐng)域內(nèi)用到的值對(duì)象??梢钥吹竭@里有PolicyProduct 這樣一個(gè)保險(xiǎn)產(chǎn)品類,在投保領(lǐng)域,我們關(guān)注的是和保單相關(guān)的某個(gè)產(chǎn)品及其快照信息,因此我們?cè)谶@里定義一個(gè)保單保險(xiǎn)產(chǎn)品類,防腐層負(fù)責(zé)把從產(chǎn)品域獲得的保險(xiǎn)產(chǎn)品信息轉(zhuǎn)換為我們關(guān)心的保單保險(xiǎn)產(chǎn)品類對(duì)象。

按照領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的最佳實(shí)踐,領(lǐng)域?qū)ο竽P椭胁辉试S出現(xiàn) service、repository 這些用以獲取外部信息的東西,它的核心概念是一個(gè)完備的實(shí)體初始化完成后,它能做什么,或者它經(jīng)歷了什么之后狀態(tài)會(huì)發(fā)生怎樣的變化。

下面是領(lǐng)域內(nèi)核心的聚合 Policy 的示例代碼:

@Getter
public class Policy {
private Long id;
private PolicyProduct product;
private List stakeHolders;
private Date issueTime;

/**
* 工廠方法
* @param product
* @param stakeHolders
* @return
*/
public static Policy create(PolicyProduct product, List stakeHolders){
Policy policy = new Policy();
policy.product = product;
policy.stakeHolders = stakeHolders;
return policy;
}

/**
* 保單出單
*/
public void issue(Long id) {
this.id = id;
this.issueTime = new Date();
}

}

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.
  • repository 是倉(cāng)儲(chǔ)包,只定義倉(cāng)儲(chǔ)接口,不關(guān)心具體實(shí)現(xiàn),具體的實(shí)現(xiàn)交由基礎(chǔ)設(shè)施層負(fù)責(zé),體現(xiàn)了依賴倒置的思想。
  • service 是領(lǐng)域服務(wù),它定義一些不屬于領(lǐng)域?qū)ο蟮男袨?,但是又有必要的操作,比如一些流程控制?/li>

(2) 用例代碼:

@Service
@AllArgsConstructor
public class PolicyService {
private final InsureUnderwriteService insureUnderwriteService;
private final PolicyRepository policyRepository;

public void issue(Policy policy) {
if(!insureUnderwriteService.underwrite(policy)){
throw new BizException("核保失敗");
}
policy.issue(IdGenerator.generate());
//保存信息
//policyRepository.save(policy);
policyRepository.create(policy);
}
}

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.

這里注意我們注掉了一行 policyRepository.save(policy);,那么為什么要區(qū)別 save 和 create 呢?

save 是領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中最正確的做法:我的聚合或者實(shí)體有變動(dòng),倉(cāng)儲(chǔ)不用關(guān)心是新建還是更新,幫我保存起來(lái)就好了。聽(tīng)上去很美好,但對(duì)關(guān)系型數(shù)據(jù)庫(kù)存儲(chǔ)卻是很不友好的。因此,在我們的場(chǎng)景里,需要違背一下書(shū)上所謂的最佳實(shí)踐,我們告訴倉(cāng)儲(chǔ)是要新建還是更新,甚至如果是更新的話更新的是哪些列。

另外領(lǐng)域驅(qū)動(dòng)的最佳實(shí)踐是基于事件驅(qū)動(dòng)的,AxonFramework 對(duì)其有完美的實(shí)現(xiàn),應(yīng)用層發(fā)出一個(gè) IssuePolicyCommand 指令,領(lǐng)域?qū)咏邮赵撝噶?,完成保單?chuàng)建后發(fā)出PolicyIssuedEvent,該 event 會(huì)被監(jiān)聽(tīng)并且持久化到 event store 中。這種方式目前看起來(lái)在我們這里落地的可能性不大,不做更多介紹。

5. 基礎(chǔ)設(shè)施層編程實(shí)踐

(1) 分包結(jié)構(gòu)

這里只展示了 repository 的實(shí)現(xiàn),但實(shí)際上這里還有 RPC 調(diào)用的二方包實(shí)現(xiàn)類注入等很多內(nèi)容。上文說(shuō)到領(lǐng)域?qū)硬魂P(guān)心倉(cāng)儲(chǔ)的實(shí)現(xiàn),交由基礎(chǔ)設(shè)施層負(fù)責(zé)?;A(chǔ)設(shè)施層可以根據(jù)需要使用關(guān)系型數(shù)據(jù)庫(kù)、緩存或者NoSQL,領(lǐng)域?qū)邮菬o(wú)感知的。這里我們以關(guān)系型數(shù)據(jù)庫(kù)為例來(lái),dao 和 dataobject 等都可以使用例如 mybatis generator 等工具生成,領(lǐng)域?qū)ο?和 dataobject 之間的轉(zhuǎn)換由 convertor 負(fù)責(zé)。

(2) 用例代碼

@Repository
@AllArgsConstructor
public class PolicyRepositoryImpl implements PolicyRepository {
private final PolicyDAO policyDAO;
private final StakeHolderDAO stakeHolderDAO;
private final PolicyConvertor policyConvertor;
private final StakeHolderConvertor stakeHolderConvertor;

@Override
public String save(Policy policy) {
throw new UnsupportedOperationException();
}

@Override
public String create(Policy policy) {
policyDAO.insert(policyConvertor.convert(policy));
stakeHolderDAO.insertBatch(stakeHolderConvertor.convert(policy));
//...其它數(shù)據(jù)入庫(kù)
return policy.getId().toString();
}

@Override
public void updatePolicyStatus(String newStatus) {

}
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.

這部分代碼比較簡(jiǎn)單,無(wú)需贅言。

五、結(jié)語(yǔ)

關(guān)于領(lǐng)域驅(qū)動(dòng),筆者仍處于初學(xué)者階段,再好的設(shè)計(jì),隨著業(yè)務(wù)的發(fā)展,代碼也難免變得混亂,這個(gè)過(guò)程中,每個(gè)參與者都有責(zé)任。最后,總結(jié)一下我們維持代碼初心的一些原則,和大家分享。

  • 深入理解業(yè)務(wù)場(chǎng)景,分析用例,進(jìn)行正確的領(lǐng)域劃分。
  • 確定好實(shí)現(xiàn)方式后,大家盡量按照既定模式/風(fēng)格編程,有異議的地方可以一起討論后統(tǒng)一改動(dòng)。
  • 不引入不必要的復(fù)雜度。
  • 不斷對(duì)系統(tǒng)設(shè)計(jì)進(jìn)行優(yōu)化改進(jìn),對(duì)繁瑣的代碼,用設(shè)計(jì)模式進(jìn)行優(yōu)化。
  • 寫(xiě)注釋。

網(wǎng)站欄目:領(lǐng)域驅(qū)動(dòng)編程,代碼怎么寫(xiě)?
分享網(wǎng)址:http://www.5511xx.com/article/cdiisog.html