DDD领域驱动设计笔记

  • Post author:
  • Post category:其他




一.前言

接触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)子域层面

├─catalog            // 商品目录子域
│  ├─application
│  ├─domain
│  ├─infrastructure
│  └─presentation
├─order              // 订单子域
│  ├─application
│  ├─domain
│  ├─infrastructure
│  └─presentation
└─store              // 商家子域
    ├─application
    ├─domain
    ├─infrastructure
    └─presentation



(2)业务模块层面

├─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



版权声明:本文为LJFPHP原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。