DDD领域驱动设计笔记

一.前言

接触DDD也有一段时间了,包括我们自己的项目就是遵循DDD设计的目录结构和代码结构,可惜团队中并没有相关的大佬能培训下这块。今天闲来无事就整理下自己的DDD笔记吧。

注:毕竟是整理自己的笔记,部分内容没有记录参考链接,见谅哈。而且仅限于自己的理解,有些错误的地方,欢迎大佬指正~

二.正文

1.什么是DDD

领域驱动设计分为两个阶段:

(1)以一种领域专家、设计人员、开发人员都能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然后将这些概念设计成一个领域模型;

(2)由领域模型驱动软件设计,用代码来实现该领域模型;。

DDD主张工程团队必须与主题专家(SME)交谈,他们是领域内的专家。这样做的原因是SME拥有关于领域的知识,这些知识应该反映在软件中。想想看,如果我要做一个股票交易平台,作为一名工程师,我对这个领域的了解够不够去做一个好的股票交易平台?如果我能和沃伦·巴菲特谈谈这个领域,这个平台可能会好得多。

2.DDD和MVC的区别

(1)DDD的分层结构
(2)ddd架构和mvc架构的对应关系

传统的mvc结构,在接到需求之后,我们可能会先设计mysql的数据表,然后根据表的字段去和业务场景进行匹配,是一种从下而上的设计思路。

而在DDD中,在接到需求之后,首先是需要进行讨论 ,明确需求以及对应的各种场景,划分需求的子域和限界上下文,乃至实体,值对象等。开发人员在对需求烂熟于心之后,开始从上而下的设计代码模型,最终实现需求。

看起来好像DDD比着传统的mvc要麻烦很多,是的,确实很麻烦。。。不过对于快速迭代或者复杂的大项目来说,遵循DDD可以让你的代码扩展性更强,高内聚低耦合的设计也能防止屎山的产生,可谓功在千秋了。

参考链接:mvc和DDD的区别

3.DDD的整体架构图

参考:美团高级技术专家:DDD 在旅游电商架构演进中的实践

这个ppt里面有关于设计DDD的具体流程,建议大家可以去看看,很仔细了。我们可以根据这张图了解下DDD的一个设计流程,从讨论到精炼出具体的模型,设计各种子域和限界上下文等等。

三、DDD的概念解释

1、战略设计和战术设计

DDD主要分为两个部分,战略设计与战术设计,战略设计围绕微服务拆分,战术设计围绕微服务构建。

细节如图:

2、战略设计相关概念

(1) 领域

这里的领域指的是业务领域。

在领域不断划分的过程中,领域会细分为不同的子域,子域可以根据自身重要性和功能属性划分为三类子域,它们分别是:核心域、通用域和支撑域。

核心域: 决定产品和公司核心竞争力的子域是核心域,它是业务成功的主要因素和公司的核心竞争力。
通用域: 没有太多个性化的诉求,同时被多个子域使用的通用功能子域是通用域。
支撑域: 还有一种功能子域是必需的,但既不包含决定产品和公司核心竞争力的功能,也不包含通用功能的子域,它就是支撑域。

(2) 限界上下文

参考:DDD(领域驱动设计)系列主题:限界上下文

将限界上下文拆解为两个词:限界和上下文。限界就是领域的边界,而上下文则是语义环境。 在很多文章中都说限界上下文就是我们的微服务,这种说法也没错,只不过限界上下文也可以是子域中的一个概念。

1)微服务

在DDD战略设计阶段识别出来的"限界上下文",会作为战术设计阶段微服务设计和拆分的主要依据,理论上"限界上下文"的边界是就微服务的物理部署边界。

2)同一个服务内

一个服务内,我们除了限定大的领域之外,还会有子域的概念。一个领域相当于一个问题域,领域拆分为子域的过程就是大问题拆分为小问题的过程。

那么各个子域之间的边界,也可以是限界上下文,保证各个子域内的聚合,语义的唯一性。

(3)防腐层

防腐层(ACL):DDD(Eric Evans)中引入的模式, 用于隔离两个系统, 允许两个系统之间在不知道对方领域知识的情况下进行集成。

1)服务之间的防腐层

1、在架构层面,通过引入防腐层有效隔离限界上下文之间的耦合;

2、防腐层同时还可以扮演适配器、调停者、外观(Facade)等角色;

3、防腐层往往属于下游限界上下文,用以隔绝上游限界上下文可能发生的变化;

2)同一个服务中的防腐层

比如下单服务,里面可能还包含商品,订单,结算支付等子域。为了保持各个子域的独立性,定义防腐层,对各个子域之间的调用做一层转换即可。

3、战术设计相关概念

(1)实体和值对象

实体一般对应业务对象,它具有业务属性和业务行为;而值对象主要是属性集合,对实体的状态和特征进行描述。但实体和值对象都只是个体化的对象,它们的行为表现出来的是个体的能力。
举例:人,也就是业务类型本身

(2)聚合

聚合就是由业务和逻辑紧密关联的实体和值对象组合而成的,聚合是数据修改和持久化的基本单元,每一个聚合对应一个仓储,实现数据的持久化。

聚合中包含实体,实体的生命周期由聚合根管理。聚合之间通过聚合根关联引用,如果需要访问其他聚合的实体,先访问聚合根,再导航到聚合内部的实体。
举例:社团,组织,部门

(3)聚合根

如果把聚合比作组织,那聚合根就是这个组织的负责人。聚合根也称为根实体,它不仅是实体,还是聚合的管理者。
聚合根之间以ID导航,OrderItem里持有ProductID而不是Product的reference。使用的时候由ProductID从ProductRepository里load出来。这在DDD里叫失联模型(disconnected model)

(4)仓储

主要是配合基础设施使用。基础设施可能是数据库,文件或者内存对象等。仓储层是对于crud做了一层抽象。例如解耦业务和mysql之前的强耦合关系,

通过调用仓储去实现持久化或者查询操作,不用去关心具体的实现。

参考:DDD系列文章

四、DDD在目录中的划分

(1)子域层面
scss 复制代码
├─catalog            // 商品目录子域
│  ├─application
│  ├─domain
│  ├─infrastructure
│  └─presentation
├─order              // 订单子域
│  ├─application
│  ├─domain
│  ├─infrastructure
│  └─presentation
└─store              // 商家子域
    ├─application
    ├─domain
    ├─infrastructure
    └─presentation
(2)业务模块层面
scss 复制代码
├─catalog            // 商品目录子域
│  ├─application        // 应用层
│  │  ├─brand
│  │  ├─category
│  │  ├─collection
│  │  └─product
│  ├─domain             // 领域层
│  │  ├─brand               // 商品品牌模块
│  │  ├─category            // 商品类目模块
│  │  ├─collection          // 商品集合模块
│  │  └─product             // 商品模块
│  ├─infrastructure     // 基础设施层
│  │  └─persistent          // 持久化
│  │      ├─jpa
│  │      ├─mybatis
│  │      └─redis
│  └─presentation       // 表现层
│      ├─graphql
│      ├─grpc
│      ├─rest
│      ├─view
│      └─websocket
└─order
    ├─application
    │  ├─dispute
    │  ├─review
    │  ├─shipping
    │  └─source
    ├─domain
    │  ├─dispute
    │  ├─review
    │  ├─shipping
    │  └─source
    ├─infrastructure
    └─presentation

end

相关推荐
uccs10 小时前
go 第三方库源码解读---go-errorlint
后端·go
bear_7920 小时前
Go操作MySQL
开发语言·go
我是前端小学生1 天前
Go语言中,函数参数是空接口的场景
go
慕城南风2 天前
Go语言中的defer,panic,recover 与错误处理
golang·go
桃园码工3 天前
1-Gin介绍与环境搭建 --[Gin 框架入门精讲与实战案例]
go·gin·环境搭建
云中谷3 天前
Golang 神器!go-decorator 一行注释搞定装饰器,v0.22版本发布
go·敏捷开发
苏三有春4 天前
五分钟学会如何在GitHub上自动化部署个人博客(hugo框架 + stack主题)
git·go·github
我是前端小学生4 天前
Go语言中的方法和函数
go
探索云原生5 天前
在 K8S 中创建 Pod 是如何使用到 GPU 的: nvidia device plugin 源码分析
ai·云原生·kubernetes·go·gpu
自在的LEE5 天前
当 Go 遇上 Windows:15.625ms 的时间更新困局
后端·kubernetes·go