DDD分層架構最佳實踐
{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還在單體應用的時候就是分層架構一說,我們用得最多的就是三層架構。而現在已經是微服務時代,在微服務架構模型比較常用的有幾個,例如:整潔架構,CQRS(命令查詢分離)以及六邊形架構。每種架構模型都有自己的應用場景,但其核心都是“","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"高內聚低耦合","attrs":{}},{"type":"text","text":"”原則。而運用","attrs":{}},{"type":"text","marks":[{"type":"bgcolor","attrs":{"color":"#F6F6F6","name":"user"}}],"text":"領域驅動設計","attrs":{}},{"type":"text","text":"(DDD)理念以應對日常加速的業務變化對架構的影響,架構的邊界越來越清晰,各司其職,這也符合微服務架構的設計思想。以領域驅動設計(DDD)爲理念的分層架構已經成爲微服務架構實踐的最佳實踐方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"一、什麼是DDD分層架構","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1. 傳統三層架構","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要了解DDD分層架構,首先先了解傳統的三層架構。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/58/5892fec13e62ae0a4aabb208c6b7f247.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"傳統三層架構流程:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第一步考慮的是數據庫設計,數據表如何建,表之間的關係如何設計","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第二步就是搭建數據訪問層,如選一個ORM框架或者拼接SQL操作","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第三步就是業務邏輯的實現,由於我們先設計了數據庫,我們整個的思考都會圍繞着數據庫,想着怎麼寫才能把數據正確地寫入數據庫中,這時CRUD的標準作法就出現了,也就沒有太多考慮面向對象,解耦的事情了,這樣的代碼對日常的維護自然是越來越困難的","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第四步表示層主要面向用戶的輸出","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2. DDD分層架構","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c5/c5cd3f68321670cb83242b9ee3a79efd.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了解決高耦合問題並輕鬆應對以後的系統變化,我們提出了運用","attrs":{}},{"type":"text","marks":[{"type":"bgcolor","attrs":{"color":"#F6F6F6","name":"user"}}],"text":"領域驅動設計","attrs":{}},{"type":"text","text":"的理念來設計架構。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"bgcolor","attrs":{"color":"#F6F6F6","name":"user"}}],"text":"此段落部分總結來源於歐創新《DDD實踐課》的《07 | DDD分層架構:有效降低層與層之間的依賴》讀後感","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1)領域層","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先我們拋開數據庫的困擾,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"先從業務邏輯入手開始","attrs":{}},{"type":"text","text":",設計時不再考慮數據庫的實現。將以前的業務邏輯層(BLL)拆分成了","attrs":{}},{"type":"text","marks":[{"type":"bgcolor","attrs":{"color":"#F6F6F6","name":"user"}}],"text":"領域層","attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"text","marks":[{"type":"bgcolor","attrs":{"color":"#F6F6F6","name":"user"}}],"text":"應用層","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"領域層聚焦業務對象的業務邏輯實現,體現現實世界業務的邏輯變化。它用來表達業務概念、業務狀態和業務規則,對於業務分析可參照:《使用領域驅動設計分析業務》","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2)應用層","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"應用層是領域層的上層,依賴領域層,是各聚合的協調和編排,原則上是不包括任何業務邏輯。它以較粗粒度的封閉爲前端接口提供支持。除了提供上層調用外,還可以包括事件和消息的訂閱。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"3) 用戶接口層","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶接口層面向用戶訪問的數據入向接口,可按不同場景提供不一樣的用戶接口實現。面向Web的可使用http restful的方式提供服務,可增加安全認證、權限校驗,日誌記錄等功能;面向微服務的可使用RPC方式提供服務,可增加限流、熔斷等功能。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"4) 基礎設施層","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基礎設施層是數據的出向接口,封裝數據調用的技術細節。可爲其它任意層提供服務,但爲了解決耦合的問題採用了依賴倒置原則。其它層只依賴基礎設施的接口,於具體實現進行分離。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"二、DDD分層代碼實現","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1. 結構模型","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/bf/bfff156e20d9b904d8fb8ecb2ae26573.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2. 目錄結構","attrs":{}}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":".\n├── pom.xml\n└── src\n ├── main\n │ ├── java\n │ │ └── fun\n │ │ └── barryhome\n │ │ └── ddd\n │ │ ├── WalletApplication.java\n │ │ ├── application\n │ │ │ ├── TradeEventProcessor.java\n │ │ │ ├── TradeMQReceiver.java\n │ │ │ └── TradeManager.java\n │ │ ├── constant\n │ │ │ └── MessageConstant.java\n │ │ ├── controller\n │ │ │ ├── TradeController.java\n │ │ │ ├── WalletController.java\n │ │ │ └── dto\n │ │ │ └── TradeDTO.java\n │ │ ├── domain\n │ │ │ ├── TradeService.java\n │ │ │ ├── TradeServiceImpl.java\n │ │ │ ├── enums\n │ │ │ │ ├── InOutFlag.java\n │ │ │ │ ├── TradeStatus.java\n │ │ │ │ ├── TradeType.java\n │ │ │ │ └── WalletStatus.java\n │ │ │ ├── event\n │ │ │ │ └── TradeEvent.java\n │ │ │ ├── model\n │ │ │ │ ├── BaseEntity.java\n │ │ │ │ ├── TradeRecord.java\n │ │ │ │ └── Wallet.java\n │ │ │ └── repository\n │ │ │ ├── TradeRepository.java\n │ │ │ └── WalletRepository.java\n │ │ └── infrastructure\n │ │ ├── TradeRepositoryImpl.java\n │ │ ├── WalletRepositoryImpl.java\n │ │ ├── cache\n │ │ │ └── Redis.java\n │ │ ├── client\n │ │ │ ├── AuthFeignClient.java\n │ │ │ └── LocalAuthClient.java\n │ │ ├── jpa\n │ │ │ ├── JpaTradeRepository.java\n │ │ │ └── JpaWalletRepository.java\n │ │ └── mq\n │ │ └── RabbitMQSender.java\n │ └── resources\n │ ├── application.properties\n │ └── rabbitmq-spring.xml\n └── test\n └── java\n\n\n\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此結構爲單一微服務的簡單結構,各層在同一個模塊中。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在大型項目開發過程中,爲了達到核心模塊的權限控制或更好的靈活性可適當調整結構,可參考《 數字錢包系統》系統結構","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"3. 領域層實現(domain)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在業務分析(《使用領域驅動設計分析業務》)之後,開始編寫代碼,首先就是寫領域層,創建","attrs":{}},{"type":"text","marks":[{"type":"bgcolor","attrs":{"color":"#F6F6F6","name":"user"}}],"text":"領域對象","attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"text","marks":[{"type":"bgcolor","attrs":{"color":"#F6F6F6","name":"user"}}],"text":"領域服務接口","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1)領域對象","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏的領域對象包括實體對象、值對象。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"實體對象","attrs":{}},{"type":"text","text":":具有唯一標識,能單獨存在且可變化的對象","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"值對象","attrs":{}},{"type":"text","text":":不能單獨存在或在邏輯層面單獨存在無意義,且不可變化的對象","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"聚合","attrs":{}},{"type":"text","text":":多個對象的集合,對外是一個整體","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"聚合根","attrs":{}},{"type":"text","text":":聚合中可代表整個業務操作的實體對象,通過它提供對外訪問操作,它維護聚合內部的數據一致性,它是聚合中對象的管理者","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代碼示例:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"// 交易\npublic class TradeRecord extends BaseEntity {\n /**\n * 交易號\n */\n @Column(unique = true)\n private String tradeNumber;\n /**\n * 交易金額\n */\n private BigDecimal tradeAmount;\n /**\n * 交易類型\n */\n @Enumerated(EnumType.STRING)\n private TradeType tradeType;\n /**\n * 交易餘額\n */\n private BigDecimal balance;\n /**\n * 錢包\n */\n @ManyToOne\n private Wallet wallet;\n\n /**\n * 交易狀態\n */\n @Enumerated(EnumType.STRING)\n private TradeStatus tradeStatus;\n\n \t@DomainEvents\n public List
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.