今天来聊一聊DDD。
在软件开发的世界里,架构从来不是一开始就复杂的。
绝大多数系统,最初都只是简单的 CRUD 系统。但随着业务的增长,系统复杂度不断增加,原有的开发模式逐渐暴露出问题。于是,新的架构思想开始出现。
DDD(Domain-Driven Design,领域驱动设计)正是在这样的背景下诞生的。
理解 DDD 的最好方式,并不是直接学习那些复杂的概念,而是从软件架构的演进过程来看:
为什么我们最终需要 DDD。
在企业软件早期,大多数系统都是围绕数据库构建的。
典型架构结构:
体验AI代码助手
代码解读
复制代码
Controller → Service → DAO → Database系统本质上是:
sql
体验AI代码助手
代码解读
复制代码
页面 + 表 + SQL开发流程通常是:
这种模式的核心特点是:
这种开发方式就是我们熟悉的:
CRUD(Create Read Update Delete)模式
这种模式非常适合:
直到今天,大量企业系统仍然采用这种模式。
但当业务复杂度上升时,问题开始出现。
随着系统规模扩大,软件工程开始强调结构化设计,于是出现了经典的 三层架构:
体验AI代码助手
代码解读
复制代码
表现层(Controller)
业务层(Service)
数据层(DAO)职责划分:
层 | 职责 |
|---|---|
Controller | 接收请求 |
Service | 业务逻辑 |
DAO | 数据访问 |
这种架构带来的改进:
三层架构成为 Java 企业开发的主流模式。
但随着系统规模继续扩大,一个新的问题逐渐出现。
在三层架构中:
于是,所有业务逻辑都堆到了:
Service层
随着业务增加,Service层逐渐变成:
体验AI代码助手
代码解读
复制代码
状态判断
流程控制
业务规则
外部系统调用
事务控制
日志处理
异常处理最终形成所谓的:
Fat Service(肥胖服务层)
一个 Service 方法可能:
Service逐渐变成:
业务逻辑的大泥球
与此同时,系统中的领域对象往往非常简单。
例如一个订单对象:
java
体验AI代码助手
代码解读
复制代码
class Order {
Long id;
Integer status;
BigDecimal amount;
}它通常只有:
而业务逻辑却写在 Service:
css
体验AI代码助手
代码解读
复制代码
orderService.pay(order)
orderService.cancel(order)
orderService.refund(order)这种模式被称为:
贫血模型(Anemic Domain Model)
问题是:
随着系统复杂度增加,这种问题会越来越严重。
当系统进入核心业务阶段时,复杂度会快速增长。
例如一个订单系统,可能涉及:
各种业务规则:
体验AI代码助手
代码解读
复制代码
已支付订单不能取消
库存不足不能下单
优惠券规则
会员等级规则
退款时间限制如果这些规则散落在:
系统很快会变得:
这时开发者往往会发现:
功能可以做,但系统越来越难改。
在这样的背景下,Eric Evans 在 2003 年提出了:
Domain-Driven Design(领域驱动设计)
DDD的核心思想是:
软件设计应该围绕业务领域进行,而不是围绕技术实现。
传统架构关注:
体验AI代码助手
代码解读
复制代码
数据库
接口
框架DDD关注:
体验AI代码助手
代码解读
复制代码
业务模型
领域概念
业务规则
系统边界简单来说:
传统架构 | DDD |
|---|---|
技术驱动 | 业务驱动 |
数据库中心 | 领域模型中心 |
DDD包含几个关键概念。
系统应该围绕业务模型设计。
例如订单系统核心对象:
css
体验AI代码助手
代码解读
复制代码
订单 Order
订单项 OrderItem
支付 Payment
优惠 Coupon领域对象不仅有数据,还应该有行为:
scss
体验AI代码助手
代码解读
复制代码
order.cancel()
order.pay()
order.refund()业务规则应该由领域对象负责。
DDD强调:
开发人员和业务人员应该使用统一的业务语言。
例如:
这些概念应该直接体现在代码中。
这样代码就能表达业务。
在复杂系统中,同一个概念在不同系统中可能含义不同。
例如“订单”:
系统 | 含义 |
|---|---|
交易系统 | 用户购买记录 |
仓储系统 | 发货任务 |
财务系统 | 结算凭证 |
DDD提出:
每个业务上下文拥有自己的模型
这就是:
Bounded Context(限界上下文)
随着微服务架构的发展,人们发现:
DDD提供了一种非常自然的服务拆分方式。
因为:
体验AI代码助手
代码解读
复制代码
Bounded Context ≈ Microservice例如:
css
体验AI代码助手
代码解读
复制代码
订单上下文 → Order Service
库存上下文 → Inventory Service
支付上下文 → Payment ServiceDDD帮助架构师回答一个关键问题:
服务应该如何拆分?
很多人认为 DDD 只是:
其实并不是。
DDD真正解决的是:
体验AI代码助手
代码解读
复制代码
复杂业务系统如何组织它帮助架构师:
从架构演进角度看,软件开发经历了这样一条路径:
markdown
体验AI代码助手
代码解读
复制代码
CRUD开发
↓
三层架构
↓
Service膨胀
↓
贫血模型
↓
业务复杂度爆炸
↓
DDD出现
↓
领域建模
↓
Bounded Context
↓
微服务架构DDD并不是为了让系统变复杂,而是为了:
用更好的模型管理复杂业务。
从架构演进的角度来看,DDD的意义在于:
让软件系统真正反映业务世界。
当系统结构与业务结构一致时,软件才能具备:
这正是领域驱动设计的核心价值。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。