当前位置: 首页 > news >正文

DDD(领域驱动设计)详解

DDD 的起源

  • 提出者:Eric Evans

  • 代表作:《Domain-Driven Design: Tackling Complexity in the Heart of Software》(《领域驱动设计:软件核心复杂性应对之道》)

  • 时间:2003年

核心目标

在复杂业务领域内,让系统的模型、设计和代码真正反映业务本质,而不是为了技术细节而妥协。

一句话总结:
✅ "以业务为中心建模,技术为业务服务。"
而不是
❌ "以数据库、接口、技术限制反向设计系统。"


后端 DDD 的核心概念

1. 领域(Domain)

  • 领域是指特定业务知识的范围,比如“电商系统”、“保险理赔”、“金融风控”。

  • 领域是整个系统的灵魂。

2. 领域模型(Domain Model)

  • 领域模型是对现实世界业务规则、状态、行为的高度抽象,通常体现在代码中(类、方法、对象等)。

  • 模型是活的,不是 UML 图,不是文档,而是可以跑的代码。

3. 战略设计(Strategic Design)

- 领域划分
  • 核心领域(Core Domain):系统成功最关键的部分。

  • 支撑子域(Supporting Subdomain):辅助核心领域,但本身不独特。

  • 通用子域(Generic Subdomain):和业务无关的通用功能(如认证、日志)。

- 限界上下文(Bounded Context)
  • 指一个明确的业务边界,在这个边界内,某个模型有统一的定义

  • 每个限界上下文内部模型一致,不同上下文之间可以存在模型冲突,需要翻译。

- 上下文映射(Context Mapping)
  • 说明各个限界上下文之间如何交互,比如合作关系、上下游关系、开放主机服务、ACL防腐层等。

4. 战术设计(Tactical Design)

- 实体(Entity)
  • 有唯一标识符(ID),生命周期长,状态可变。

- 值对象(Value Object)
  • 无需 ID,根据属性值判等,不可变,比如 Money、Address。

- 聚合(Aggregate)
  • 由实体和值对象组成的集合,有一个聚合根(Aggregate Root)作为入口。

- 仓储(Repository)
  • 提供聚合的持久化接口(通常是数据库交互)。

- 领域服务(Domain Service)
  • 某些业务逻辑不属于某一个实体,抽出来成为领域服务。

- 应用服务(Application Service)
  • 负责协调领域对象,处理用户请求,返回响应,但不承载业务规则。


质疑:为什么后端要用 DDD?

适用场景:

  • 系统业务极度复杂,无法用简单的 CRUD 应付,比如:

    • 银行信贷系统

    • 保险理赔系统

    • ERP、供应链管理系统

  • 团队规模大,必须形成统一的业务语言和建模方式。

  • 需要长期演进,保持系统可扩展、可理解。

不适用场景:

  • 简单 CRUD 服务、信息展示系统、小型内部工具,不需要 DDD。

  • 领域模型过重,反而增加开发和学习负担,得不偿失。


DDD 真正的挑战

  • 高认知成本:要理解业务、建模,远比堆 API 难。

  • 团队协作要求高:要有共同的领域语言,业务方、开发、测试、产品经理之间必须统一。

  • 建模难度大:真正能建出好模型的人很少。

  • 落地难度大:很多公司打着 DDD 旗号,实际上只是加了几层 service 目录而已。


我的专业观点

  1. DDD不是银弹,是为复杂业务系统量身定制的方法,不是所有项目都应该用。

  2. 战略设计远比战术设计重要。不要一开始就沉迷 entity、repository,而是先搞清限界上下文和领域划分。

  3. 实践要渐进式引入。一开始可以局部使用 DDD 思想,随着团队熟悉后逐步扩展。

  4. DDD讲究语言统一,产品经理、开发、测试都应该用同一套业务术语,否则 DDD会形同虚设。

  5. 不要迷信架构,DDD只是帮助你更好地服务业务,而不是成为炫耀的资本。


总结

后端 DDD 的精髓在于:以真实业务为中心进行建模,控制复杂度,提升长期演进能力。
真正掌握 DDD,不是掌握了一堆术语,而是能用业务语言自然地解释系统设计背后的每一个决策。

http://www.xdnf.cn/news/187651.html

相关文章:

  • 【C++类与对象高频面试问题总结2】
  • 在VS2022中使用Lua与c交互(二)
  • 读书笔记--华为从偶然到必然之创新与技术开发阅读有感
  • 交换机配置DHCP
  • 使用python实现自动化拉取压缩包并处理流程
  • 深入理解CSS3:Flex/Grid布局、动画与媒体查询实战指南
  • Python初学 有差异的知识点总结(一)
  • 构建“云中”高并发:12306技术改造的系统性启示
  • mac 基于Docker安装minio
  • Flutter介绍、Flutter Windows Android 环境搭建 真机调试
  • ETL架构、数据建模及性能优化实践
  • GPU 架构入门笔记
  • git pull报错error: cannot lock ref ‘refs/remotes/origin/feature/xxx
  • 【C语言】初阶算法相关习题(二)
  • Python-librosa库提取音频数据的MFCC特征
  • 线下CPG零售的核心:POG与销量的循环优化
  • 浅谈PCB传输线(一)
  • docker安装Canal1.1.5,MySQL5.7踩坑
  • Ubuntu中C++项目安装二次规划库——qpOASES 库
  • 论文阅读_Search-R1_大模型+搜索引擎
  • 怎么样才能在idea中写入spark程序
  • 无人船 | 图解基于LQR控制的路径跟踪算法(以全驱动无人艇WAMV为例)
  • 仙宫云ComfyUI —【Wan2.1】AI视频生成部署
  • 【计算机视觉】TorchVision 深度解析:从核心功能到实战应用 ——PyTorch 官方计算机视觉库的全面指南
  • VINS-FUSION:跑通手机录制数据
  • EasyRTC嵌入式音视频通信SDK智能安防与监控系统的全方位升级解决方案
  • 杰理-安卓通过map获取时间的时候,部分手机切换sbc和aac时候单耳无声音
  • 超级好用的​​参数化3D CAD 建模​​图形库 (CadQuery库介绍)
  • 【亚马逊云】AWS Wavelength 从理论讲解到实验演练
  • Android Compose vs 传统View系统:全面对比与选型指南