【DDD】領域驅動設計實踐 —— 框架實現

本文主要介紹了基於SpringMVC+mybatis對DDD思想的落地實現框架。本文爲【DDD】系列文章中的其中一篇,其餘內容可參考:使用領域驅動設計思想實現業務系統html

框架實現圖

該框架實現基本和DDD的指導思想契合,主要分爲四層,且將關注點放在了domain層。下面將逐層介紹各個組件的職責。java

框架詳述

User Interface層

門面層,對外以各類協議提供服務,該層須要明肯定義支持的服務協議、契約等。包含:redis

dto

包括request和response兩部分,經過它定義入參和出參的契約,在dto層可使用基礎設施層的validation組件完成入參格式校驗;mongodb

controller

支持不一樣訪問協議的控制器實現,好比:http/restful風格、tcp/二進制流協議、mq消息/json對象等等。json

controller使用基礎設施層公共組件完成許多通用的工做:restful

  • 調用RequestMapping(SpringMVC公共組件)完成servlet路由;
  • 調用checklogin完成登陸態/權限校驗;
  • 調用logging組件完成日誌記錄;
  • 調用message-resource組件完成錯誤信息轉義,支持I18N;

application層

service

應用服務層,組合domain層的領域對象和基礎設施層的公共組件,根據業務須要包裝出多變的服務,以適應多變的業務服務需求。mybatis

應用服務層主要訪問domain領域對象,完成服務邏輯的包裝。oracle

應用服務層也會訪問基礎設施層的公共組件,如rabbitmq,完成領域消息的生產等。app

assembler

組裝器,負責將多個domain領域對象組裝爲須要的dto對象,好比查詢帖子列表,須要從Post(帖子)領域對象中獲取帖子的詳情,還須要從User(用戶)領域對象中獲取用戶的基本信息。框架

組裝器中不該當有業務邏輯在裏面,主要負責格式轉換、字段映射等職責。

domain層

業務領域層,是咱們最應當關心的一層,也是最多變的一層,須要保證這一層是高內聚的。確保全部的業務邏輯都留在這一層,而不會遺漏到其餘層。按照ddd(domain driven design)理論,主要有以下概念構成:

domain entity

領域實體。有惟一標識,可變的業務實體對象,它有着本身的生命週期。好比社區這一業務領域中,‘帖子’就是一個業務實體,它須要有一個惟一性業務標識表徵,同時他的狀態和內容能夠不斷髮生變化。

domain value object

領域值對象。能夠沒有惟一性業務標識,且一旦定義,他是不可變的,它一般是短暫的。這和java中的值對象(基本類型和String類型)相似。好比社區業務領域中,‘帖子的置頂信息’能夠理解爲是一個值對象,不須要爲這一值對象定義獨立的業務惟一性標識,直接使用‘帖子id‘即可表徵,同時,它只有’置頂狀態‘和’置頂位置‘,一旦其中一個屬性須要發生變化,則重建值對象並賦值給’帖子‘實體的引用,不會對領域帶來任何負面影響。

domain factory

領域對象工廠。用於複雜領域對象的建立/重建。重建是指經過respostory加載持久化對象後,重建領域對象。

domain service

領域服務。區別於應用服務,他屬於業務領域層。

能夠認爲,若是某種行爲沒法歸類給任何實體/值對象,則就爲這些行爲創建相應的領域服務便可。好比:轉帳服務(transferService),須要操做借方/貸方兩個帳戶實體。

傳統意義上的util static方法中,涉及到業務邏輯的部分,均可以考慮納入domain service。

domain event

領域事件。領域中產生的一些消息事件,經過事件通知/訂閱的方式,能夠在性能和解耦層面獲得好處。

repository

倉庫。咱們將倉庫的接口定義歸類在domain層,由於他和domain entity聯繫緊密。倉庫用戶和基礎實施的持久化層交互,完成領域對應的增刪改查操做。

倉庫的實際實現根據不一樣的存儲介質而不一樣,能夠是redis、oracle、mongodb等。

鑑於如今社區服務的存儲介質有三套:oracle、redis、mongodb,且各個存儲介質的字段屬性名不一致,所以須要使用translator來作翻譯,將持久化層的對象翻譯爲統一的領域對象。

translator

翻譯器。將持久化層的對象翻譯爲統一的領域對象。

翻譯器中不該當有業務邏輯在裏面,主要負責格式轉換、字段映射等職責。

infrastructure層

基礎設施層提供公共功能組件,供controller、service、domain層調用。

repository impl

對domain層repository接口的實現,對應每種存儲介質有其特定實現,如oracle的mapper,mongodb的dao等等。repository impl會調用mybatis、mongo client、redis client完成實際的存儲層操做。

checkLogin

權限校驗器,斷定客戶端是否有訪問該資源的權限。提供給User Interface層的Controller調用。

exception

異常分類及定義,同時提供公共的異常處理邏輯,具體由ExceptionHandler實現。

transport

transport完成和第三方服務的交互,能夠有多種協議形式的實現,如http+json、tcp+自定義協議等,配套使用的還有Resolver解析器,用於對第三方服務的請求和響應進行適配,提供一個防腐層(AnticorruptionLayer,DDD原書P255)的做用。

transcation

提供事務管理,交給Spring管理。

logging

日誌模塊,記錄trace日誌,使用log4j完成。

message resource

消息資源管理,交給Spring統一管理。

模塊結構

本節介紹COMMUNITY系統的模塊結構,因爲是使用java語言實現,也就是java工程中的包結構,能夠直觀地看出框架的落地實現效果。

 各個package的詳細解釋參考上節框架詳述,着重注意以下幾點:

  • factory是專職爲model服務的,所以放入對應的entity的modle package中;
  • domain.repository包裏面只有倉庫的接口定義,實際的實現交給了infrastrcture中的repository module,該作法被稱做"依賴倒置",好處在於確保domoain層語義完整,同時對確保業務領域的一致性也有幫助,再者能夠在domain實現內存形式的repository啞實現,從而讓domain能夠真正脫離掉infrastructure;
  • translator module正常狀況下不須要,但在重構老系統時,每每須要隔離掉存儲模型對業務模型的影響,使用translator來說存儲模型翻譯爲業務模型;
  • infrastructure.repository做爲倉庫層,會將實體的增刪改查操做委託給具體的存儲層服務,如oracle對應的mapper實現,mongodb對應dao實現,還有redis的實現;
  • COMMUNITY中domain event的生產者和消費者實現均交給infrastructure.rabbitmq package實現。
相關文章
相關標籤/搜索