领域驱动设计 (DDD) 总结

领域驱动设计(DDD)是一种软件开发方法论,通过建立领域模型,使用领域专家、设计人员、开发人员都能理解的通用语言进行交流,以领域模型驱动软件设计。本文详细介绍了领域模型的构成,如实体、值对象、领域服务、聚合及聚合根,强调了通用语言、不变性封装、小聚合设计等原则,以及领域驱动分层架构。同时,探讨了领域模型的设计步骤、聚合设计原则,以及领域层与其他层的交互,如应用层的交互和工作单元的实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://cloud.tencent.com/developer/article/1662032

一. DDD 简述

DDD (Domain-Driven Design),即领域驱动设计是思考问题的方法论,用于对实际问题建模,它以一种领域专家、设计人员、开发人员都能理解的通用语言作为相互交流的工具,然后将这些概念设计成一个领域模型。由领域模型驱动软件设计,用代码来实现该领域模型。所以,DDD 的核心是建立正确的领域模型

二. 领域模型

2.1 领域模型

定义上说,领域模型是对具有某个边界的领域的一个抽象,反映了领域内用户业务需求的本质;领域模型是有边界的,只反映了我们在领域内所关注的部分,确保了我们的软件的业务逻辑都在一个模型中,这样对提高软件的可维护性业务s可理解性以及可重用性方面都有很好的帮助。领域模型只反映业务,和任何技术实现无关,它不仅能反映领域中的一些实体概念(如货物,书本,应聘记录,地址等),还能反映领域中的一些过程概念(如资金转账等)。 领域模型贯穿软件分析、设计,以及开发的整个过程,领域专家、设计人员、开发人员通过领域模型进行交流,彼此共享知识与信息。了让领域模型看的见,我们需要用一些方法来表示它。是表达领域模型最常用的方式,但并不是唯一的表达方式,代码、文字描述也能表达领域模型。

2.2 通用语言

领域驱动设计的一个核心的原则是使用一种基于模型的语言。因为模型是软件满足领域的共同点,它很适合作为这种通用语言的构造基础。使用模型作为语言的核心骨架,要求团队在进行所有的交流是都使用一致的语言(包括演讲、文字和图形),需要确保团队使用的语言在所有的交流形式中看上去都是一致的,这种语言被称为**通用语言 (Ubiquitous Language)**。在建模过程中,通用语言广泛尝试于推动软件专家和领域专家之间的沟通,从而发现要在模型中使用的主要的领域概念。

2.3 领域建模思考问题

  1. 我们设计领域模型时不能以用户为中心作为出发点去思考问题,不能老是想着用户会对系统做什么;而应该从一个客观的角度,根据用户需求挖掘出领域内的相关事物,思考这些事物的本质关联及其变化规律作为出发点去思考问题。
  2. 领域模型是排除了人之外的客观世界模型
    • 虽然领域模型包含人所扮演的参与者角色,但是一般情况下不要让参与者角色在领域模型中占据主要位置。如果以人所扮演的参与者角色在领域模型中占据主要位置,那么各个系统的领域模型将变得没有差别。因为软件系统就是一个人机交互的系统,都是以人为主的活动记录或跟踪。比如:
      • 论坛中如果以人为主导,那么领域模型就是:人发帖,人回帖,人结贴,等等;
      • DDD的例子中,如果是以人为中心的话,就变成了:托运人托运货物,收货人收货物,付款人付款等等;
    • 因此,当我们谈及领域模型时,已经默认把人的因素排除开了,因为领域只有对人来说才有意义,即人是在领域范围之外的,如果人也划入领域,领域模型将很难保持客观性。
    • 领域建模是建立虚拟模型让我们现实的人使用,而不是建立虚拟空间,去模仿现实。

例:以 DDD 之父的货物运输系统为例,他描述领域模型如下:

  1. 一个货物 (Cargo) 涉及多个客户(Customer,比如托运人、收货人、付款人),每个客户承担不同的角色;
  2. 货物只有一个运送目标;
  3. 由一系列规格 (Specification) 的运送动作 (Carrier Movement) 来完成目标的运输。

由上面可以看到,上述这段描述完全以货物为中心,把客户看成是货物在某个场景中可能会涉及到的关联角色。他完全没有从用户的角度去描述领域模型,而是以领域内的相关事物为出发点,考虑这些事物的本质关联及其变化规律的。 其实如果以用户为中心来思考领域模型的思维,这只是停留在需求的表面,而没有挖掘出真正的需求的本质。我们在做领域建模时需要努力挖掘用户需求的本质,这样才能真正实现用户需求。

三. 领域驱动分层架构

 

  1. 用户界面/展现层:负责向用户展现信息以及解释用户命令。更细的方面来讲就是:
    • 请求应用层以获取用户所需要展现的数据;
    • 发送命令给应用层要求其执行某个用户命令;
  2. 应用层:很薄的一层,定义软件要完成的所有任务。对外为展现层提供各种应用功能(包括查询或命令),对内调用领域层(领域对象或领域服务)完成各种业务逻辑,应用层不包含业务逻辑。
  3. 领域层:负责表达业务概念,业务状态信息以及业务规则,领域模型处于这一层,是业务软件的核心
  4. 基础设施层:本层为其他所有层提供通用的技术能力,包括提供了层间的通信,为领域层实现持久化机制等。总之,基础设施层可以通过架构和框架来支持其他层的技术需求;

四. 领域驱动设计的模式

 

目录

一. DDD 简述

二. 领域模型

2.1 领域模型

2.2 通用语言

2.3 领域建模思考问题

三. 领域驱动分层架构

四. 领域驱动设计的模式

4.1 关联的设计

4.2 实体 (Entity)

4.3 值对象 (Value Object)

4.4 领域服务 (Domain Service)

4.5 聚合 (Aggregate)、聚合根 (Aggregate Root)

4.6 工厂 (Factory)

4.7 仓库 (Repository)

五. 领域模型的设计步骤

六. 聚合设计原则

6.1 不变性的封装

6.2 小聚合设计

6.3 通过 ID 关联聚合

6.4 一致性

七. 与领域层的交互

7.1 应用层的交互

7.2 工作单元的实现方法

八. 限界上下文 (Bounded Context)

九. 上下文图 (Context Map)

9.1 上下文图类型

9.2 上下文图的思考


4.1 关联的设计

关联本身不是一个模式,但它在领域建模的过程中非常重要,所以需要在探讨各种模式之前,先讨论一下对象之间的关联该如何设计。我觉得对象的关联的设计可以遵循如下的一些原则:

  1. 关联尽量少,对象之间的复杂的关联容易形成对象的关系网,这样对于我们理解和维护单个对象很不利,也很难划分对象与对象之间的边界;反过来,减少关联有助于简化对象之间的遍历;
  2. 对多的关联也许在业务上是很自然的,通常我们会用一个集合来表示一对多的关系。但我们往往也需要考虑到性能问题,尤其是当集合内元素非常多的时候,此时往往需要通过单独查询来获取关联的集合信息;
  3. 关联尽量保持单向的关联;
  4. 在建立关联时,我们需要深入去挖掘是否存在关联的限制条件,如果存在,那么最好把这个限制条件加到这个关联上;往往这样的限制条件能将关联化繁为简,即可以将多对多简化为一对多,或将一对多简化为一对一;

4.2 实体 (Entity)

实体就是领域中需要唯一标识的领域概念。假设有两个实体,如果唯一标识不一样,那么即便实体的其他所有属性都一样,我们也认为他们两个不同的实体。因为实体有生命周期,实体从被创建后可能会被持久化到数据库,然后某个时候又会被取出来。所以,如果我们不为实体定义一种可以唯一区分的标识,那我们就无法区分到底是这个实体还是哪个实体。 我们不应该给实体定义太多的属性或行为,而应该寻找关联,发现其他一些实体或值对象,将属性或行为转移到其他关联的实体或值对象上。

例:

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值