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

领域驱动设计(DDD)是什么?


领域驱动设计(DDD)是什么?


在软件开发的世界里,我们总在寻找那把打开业务之门的钥匙。有人迷恋MVC的简洁,有人追逐微服务的潮流,而DDD(领域驱动设计)则像一位沉默的智者,提醒着我们:软件不是代码的堆砌,而是对现实世界的映射

在软件开发中,你是否遇到过这些问题?

  • 业务逻辑散落各处,修改一个需求需要改动几十个文件。
  • 系统迭代后变成“大泥球”,新成员上手需要啃几个月代码
  • 技术语言与业务语言割裂,开发与产品经理频繁“鸡同鸭讲”。

这些痛点背后的本质是:软件复杂性失控。而领域驱动设计(Domain-Driven Design,DDD)正是为解决这些问题而生。


一、DDD是什么?

DDD:不是框架,而是一种思维方式

1. 核心哲学的三重维度

  • 认知维度:建立开发团队与业务专家的统一语言
    (如将"用户授信"转化为CreditEvaluation领域服务)
  • 架构维度:通过限界上下文切割业务复杂度
    (支付上下文与风控上下文的关系如同两个国家的贸易协定)
  • 工程维度:充血模型让代码成为活的业务文档
    (对比传统贫血模型,DDD的Order类包含calculateTotal()等业务方法)

DDD(Domain-Driven Design)是一种以业务领域为核心的软件设计方法,由Eric Evans在2003年提出。它并非具体的技术框架或工具,而是一套应对复杂业务系统的设计哲学和实践方法论

DDD的核心目标:

  1. 消除技术实现与业务需求的鸿沟
  2. 通过领域模型管理复杂性
  3. 构建可持续演进的软件系统

类比理解
传统开发如同“拼乐高”——按图纸组装固定模块;
DDD开发则是“造乐高”——先理解用户想构建什么,再设计专属的积木块。


二、DDD的核心理念

1. 统一语言(Ubiquitous Language)

  • 问题:开发用“User”,产品说“客户”,DBA称“account”
  • 解法:建立团队共识的术语表
// 代码体现统一语言  
public class Customer {  // 统一使用"客户"而非"用户"private CustomerId id;  private AccountCollection accounts; // 账户集合
}

2. 限界上下文(Bounded Context)

  • 定义:业务子领域的独立边界
  • 案例:电商系统中的“订单上下文” vs “支付上下文”
上下文核心概念交互方式
订单上下文购物车、优惠券、库存预留发布“订单已创建”事件
支付上下文支付单、退款规则、渠道对接监听事件触发支付流程

3. 领域模型(Domain Model)

传统贫血模型 vs DDD充血模型

// 贫血模型:数据与行为分离
public class Order {private Long id;private BigDecimal amount;
}public class OrderService {public void applyDiscount(Order order, BigDecimal discount) {order.setAmount(order.getAmount().multiply(discount));}
}// 充血模型:行为内聚在领域对象
public class Order {private Long id;private BigDecimal amount;public void applyDiscount(BigDecimal discount) {this.amount = this.amount.multiply(discount);}
}

三、DDD的核心模式

1. 战略设计:划分业务版图

  • 事件风暴(Event Storming):通过领域事件识别业务边界

  • 上下文映射(Context Mapping):定义跨上下文协作模式

2. 战术设计:构建领域模型

(1)领域对象类型
类型定义案例
实体(Entity)唯一标识 + 可变状态用户(User)、订单(Order)
值对象(Value Object)不可变属性集合地址(Address)、金额(Money)
聚合(Aggregate)一致性边界的领域对象集群订单聚合(含Order、OrderItem)
(2)分层架构
├── interfaces    // 适配层:对接外部输入(API/消息)
├── application   // 应用层:编排领域对象完成用例
├── domain        // 领域层:充血模型核心
└── infrastructure// 基础设施:数据库/缓存实现

四、DDD的落地实践

1. 仓储模式(Repository)

传统DAO vs DDD仓储

// 传统DAO:直接操作数据库
public interface OrderDao {void insert(Order order);
}// DDD仓储:领域模型与持久化的桥梁
public interface OrderRepository {Order findById(OrderId id);void save(Order order);
}// 基础设施层实现
@Repository
public class JpaOrderRepository implements OrderRepository {@Overridepublic Order findById(OrderId id) {// 调用JPA实现查询}
}

2. 领域事件(Domain Event)

public class OrderPaidEvent {private OrderId orderId;private LocalDateTime paidTime;
}// 应用服务发布事件
public class OrderApplicationService {@Transactionalpublic void payOrder(OrderId id) {Order order = repository.findById(id);order.pay();eventPublisher.publish(new OrderPaidEvent(order.getId()));}
}

五、何时使用DDD?

适用场景:

  • 业务规则复杂(如金融风控、电商促销)
  • 长生命周期系统(需持续迭代3年以上)
  • 多团队协作开发(明确上下文边界)

不适用场景:

  • 简单CRUD管理系统
  • 短期/实验性项目
  • 强事务一致性场景(如银行核心转账)

六、DDD的价值收益

某保险系统重构前后对比:

指标重构前(传统架构)重构后(DDD)提升幅度
需求交付周期2周3天85%
生产缺陷率0.8%0.1%87.5%
新功能开发冲突高频几乎为零90%

结语:DDD的本质是思维方式

DDD不是银弹,而是持续探索业务本质的旅程。它要求开发者:

  1. 深入理解业务——与领域专家共同建模
  2. 拥抱变化——通过限界上下文隔离变更影响
  3. 保持谦逊——承认没有一劳永逸的设计

正如Eric Evans所说:

“优秀的软件不是构建出来的,而是演化出来的。”

从今天开始,尝试用DDD的视角重新审视你的系统,或许会发现一片新大陆。

相关文章:

领域驱动设计(DDD)是什么?

领域驱动设计(DDD)是什么? 在软件开发的世界里,我们总在寻找那把打开业务之门的钥匙。有人迷恋MVC的简洁,有人追逐微服务的潮流,而DDD(领域驱动设计)则像一位沉默的智者,…...

JavaScript 模块 vs C# 类:封装逻辑的两种哲学

引言 在现代软件开发中,模块化和面向对象设计是代码组织的核心课题。本文通过对比 JavaScript 模块(ES6 Module)与 C# 类(Class)的实现方式,探讨两种语言在封装逻辑时的不同哲学,并给出实际应用…...

2.2 企业级ESLint/Prettier规则定制

文章目录 1. 为什么需要企业级代码规范2. 工具选型对比3. 完整配置流程3.1 项目初始化3.2 ESLint深度配置3.3 Prettier精细配置3.4 解决规则冲突4. 高级定制方案4.1 自定义ESLint规则4.2 扩展Prettier插件5. 团队协作策略5.1 配置共享方案5.2 版本控制策略6. CI/CD集成7. 常见问…...

Linux学习(十五)(故障排除(ICMP,Ping,Traceroute,网络统计,数据包分析))

故障排除是任何 Linux 用户或管理员的基本技能。这涉及识别和解决 Linux 系统中的问题。这些问题的范围包括常见的系统错误、硬件或软件问题、网络连接问题以及系统资源的管理。Linux 中的故障排除过程通常涉及使用命令行工具、检查系统和应用程序日志文件、了解系统进程&#…...

DeepIn Wps 字体缺失问题

系统缺失字体 Symbol 、Wingdings 、Wingdings2、Wingdings3、MT—extra 字体问题 问了下DeepSeek 在应用商店安装或者在windows 里面找 装了一个GB-18030 还是不行 在windows里面复制了缺失的字体 将字体复制到DeepIn 的字体目录(Ubuntu 应该也是这个目录&am…...

(二分 数学推导 统计公平数对的数目)leetcode 2563

数学推导&#xff1a; lower < nums[i] nums[j] < upper且0 < i < j < n 则lower-nums[j]<nums[i]<upper-nums[j] 找到这个范围的nums[i]的个数就是我们要的值 所以枚举j 在0--&#xff08;j-1&#xff09;的范围内 找到第一个大于等于lower-nums[j]…...

临界比例法PID调整-附带pidtune工具和GA算法

代码已上传&#xff1a;计算机控制系统PID参数整定法资源-CSDN文库 1背景 为了模拟PID参数整定&#xff0c;把教材上的案例进行分析。 1题目 单位闭环传递函数&#xff0c;开环传函G(s)1/((s1)(s2)), Ts0.1s, PID调整器输出后&#xff0c;接零阶保持器ZOH。 2 代码 PID含积…...

LabVIEW基于双通道FFT共轭相乘的噪声抑制

对于双通道采集的含噪信号&#xff0c;通过FFT获取复数频谱后&#xff0c;对第二通道频谱取共轭并与第一通道频谱相乘&#xff0c;理论上可增强相关信号成分并抑制非相关噪声。此方法适用于通道间信号高度相关、噪声独立的场景&#xff08;如共模干扰抑制&#xff09;。以下为L…...

小程序SSL证书过期怎么办?

SSL证书就像小程序的“安全锁”&#xff0c;一旦过期&#xff0c;用户访问时会被提示“不安全”&#xff0c;轻则流失客户&#xff0c;重则数据泄露&#xff01;作为企业负责人&#xff0c;如何快速解决证书过期问题&#xff1f;又该如何避免再次踩坑&#xff1f;这篇指南给你答…...

ELK日志分析实战

ELK日志分析实战&#xff1a;从异常流量定位提权攻击 摘要&#xff1a;本文通过模拟真实攻防场景&#xff0c;结合ELK技术栈&#xff08;ElasticsearchLogstashKibana&#xff09;&#xff0c;演示如何从海量服务器日志中快速定位异常流量并追踪提权攻击行为。包含完整的日志收…...

阿里云操作系统控制台实战评测:提升云资源管理与监控效率

文章目录 前言产品介绍操作系统控制台体验阿里云操作系统开通 帮助与总结建议 前言 随着云计算和虚拟化技术的发展&#xff0c;操作系统控制台作为运维管理的核心工具之一&#xff0c;在现代IT环境中发挥着越来越重要的作用。它提供了一种更加直观、高效的方式来管理操作系统&…...

Docker构建启动jar包

Docker构建启动jar包 1、首先是把java服务打包成jar包 mvn clean install -Dmaven.skip.testtrue package -Pprod这个命令的意思是&#xff0c;跳过测试&#xff0c;打包prod环境。 2、编写Dockerfile文件 # 拉取jdk8作为基础镜像 FROM registry.supos.ai/library/openjdk:…...

微信小程序使用的SSL证书在哪里申请?

在数字化时代&#xff0c;微信小程序已成为众多企业和个人开发者触达用户的重要平台。然而&#xff0c;随着网络安全威胁的日益严峻&#xff0c;确保小程序数据传输的安全性显得尤为重要。SSL证书&#xff0c;作为加密通信的基石&#xff0c;是保障小程序安全不可或缺的一环。 …...

基于langchain+llama2的本地私有大语言模型实战

Langchain功能 LangChian 作为一个大语言模型&#xff08;LLM, Large Language Model&#xff09;开发框架&#xff0c;是 LLM 应用架构的重要一环。借助 LangChain&#xff0c;我们可以创建各种应用程序&#xff0c;包括聊天机器人和智能问答工具。 AI模型&#xff1a;包含各…...

如何使用postman来测试接口

一、postman的介绍与下载 可参考&#xff1a; https://blog.csdn.net/freeking101/article/details/80774271 二、api获取网站 阿里云API应用市场 地址&#xff1a;云市场_镜像市场_软件商店_建站软件_服务器软件_API接口_应用市场 - 阿里云 三、具体测试过程 可模拟浏览…...

深入剖析B树、B+树与B*树:从二叉树到多叉树的演进

引言 在计算机科学中&#xff0c;树结构是数据存储和检索的核心工具之一。从二叉树到二叉排序树&#xff0c;再到平衡二叉树&#xff0c;我们已经看到了这些数据结构在高效处理数据方面的优势。然而&#xff0c;随着数据量的爆炸式增长&#xff0c;二叉树的局限性逐渐显现出来…...

《算法篇:三数之和问题的两种解法》

问题描述 给定一个包含 n 个整数的数组 nums&#xff0c;判断 nums 中是否存在三个元素 a&#xff0c;b&#xff0c;c &#xff0c;使得 a b c 0 &#xff1f;找出所有满足条件且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 给定数组 nums [-1, 0,…...

【2025】基于springboot+uniapp的乡村旅游小程序系统统(源码、万字文档、图文修改、调试答疑)农家乐预约

乡村旅游小程序系统通过 Spring Boot 与 uniapp 技术栈的深度整合&#xff0c;为乡村旅游产业打造了一个功能全面、交互流畅、性能稳定的综合服务平台。系统根据不同角色&#xff08;管理员、商家、用户&#xff09;的业务需求&#xff0c;提供了针对性的功能模块&#xff0c;实…...

DeepSeek Kimi详细生成PPT的步骤

以下是使用 DeepSeek 和 Kimi 协作生成 PPT 的详细步骤&#xff0c;结合了两者的优势实现高效创作&#xff1a; 第一步&#xff1a;使用 DeepSeek 生成 PPT 大纲或内容 明确需求并输入提示词 在 DeepSeek 的对话界面中&#xff0c;输入具体指令&#xff0c;要求生成 PPT 大纲或…...

【Film】MM-StoryAgent:沉浸式叙事故事书视频生成,具有跨文本、图像和音频的多代理范式

MM-StoryAgent:沉浸式叙事故事书视频生成,具有跨文本、图像和音频的多代理范式 https://arxiv.org/abs/2503.05242 MM-StoryAgent: Immersive Narrated Storybook Video Generation with a Multi-Agent Paradigm across Text, Image and Audio The rapid advancement of larg…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...