DDD:领域驱动设计的初步认识

DDD:领域驱动设计的初步认识

DDD(领域驱动设计)一直是 Java 后端中讨论度很高的话题。有人觉得它是复杂系统的救星,也有人觉得它过度设计。在真正学习 DDD 的各种概念之前,更重要的问题其实是:DDD 到底解决了什么问题?

目录

  • 传统架构的痛点
  • [DDD 是什么](#DDD 是什么)
  • [DDD 和传统架构的区别](#DDD 和传统架构的区别)
  • [什么时候该用 DDD](#什么时候该用 DDD)
  • 小结

传统架构的痛点

做 Java 后端开发的同学对三层架构一定不陌生:Controller 接收请求,Service 处理业务逻辑,DAO 操作数据库。这个分层方式清晰直观,上手也快,很多项目一开始都是这么搭的。

但随着业务越来越复杂,真正的问题不是 Controller、Service、DAO 三层不够,而是业务规则越来越分散。

创建订单能不能取消?什么时候允许退款?库存什么时候扣减?积分什么时候发放?这些规则到底应该写在哪里?有人写在 Controller,有人写在 Service,还有人放进各种 Util 或 Manager 中。时间一长,同一个业务被拆散到多个地方,维护越来越困难。

根本原因在于:传统三层架构按技术职责组织代码,而不是按业务能力组织代码。

Controller 负责接收请求,Service 负责业务处理,DAO 负责数据访问。随着业务越来越复杂,一个业务会同时分散到多个技术层中,业务本身的边界反而越来越模糊。

DDD 是什么

DDD,全称 Domain-Driven Design,领域驱动设计。2003 年 Eric Evans 在同名书中提出。

让代码的结构反映业务的结构,而不是数据库表的结构。 换句话说,就是先思考业务,再思考技术。

传统架构下,代码的组织方式是按技术分层的:Controller 层、Service 层、DAO 层。每个层关心的是技术职责,不是业务职责。而 DDD 的思路是反过来:先搞清楚业务领域是怎么划分的,再按业务领域来组织代码。

举个例子。一个电商系统,按传统架构分层是这样的:

复制代码
controller/
    OrderController.java
    UserController.java
    ProductController.java
service/
    OrderService.java
    UserService.java
    ProductService.java
dao/
    OrderDao.java
    UserDao.java
    ProductDao.java

按 DDD 的思路组织是这样的:

复制代码
order/
    Order.java
    OrderService.java
    ...
user/
    User.java
    UserService.java
    ...
product/
    Product.java
    ProductService.java
    ...

在传统架构下,一个订单相关的逻辑散落在 Controller、Service、DAO 三个目录里。DDD 下,订单相关的所有东西都在 order 包里。修改订单相关功能时,大部分代码都会集中在 order 模块,而不是在 Controller、Service、DAO 三层之间来回切换。

DDD 和传统架构的区别

两种架构的核心差异可以从几个维度来看:

维度 传统架构 DDD
设计中心 数据库表 领域模型
代码组织 按技术分层(Controller/Service/DAO) 按业务领域划分(order/user/product)
业务逻辑归属 散落在各层 内聚到领域对象中
Entity 对象 数据载体(贫血模型) 封装数据和业务行为(充血模型)
数据库依赖 Service 直接依赖 DAO 通过 Repository 接口隔离
新增功能 可能要改三个层 只改对应的领域模块

传统架构下,Service 层是业务逻辑的主要承载者,但 Service 本身是一个"什么都能往里放"的容器。一个 OrderService 可能同时负责订单创建、订单查询、订单取消、订单退款、订单状态流转......职责越来越多,代码越来越长。

DDD 做的事情是把业务逻辑下沉到领域对象里。Order 实体不只是一个数据容器,它维护自己的业务规则,例如哪些状态允许取消、哪些订单允许退款、状态如何流转等。Service 层变成一个协调者,负责编排领域对象完成业务流程,而不是把所有逻辑都扛在自己身上。

打个比方。传统架构更像是把所有 Java 文件按"类型"放到不同文件夹:Controller、Service、DAO。DDD 更像是按"业务模块"整理代码:订单相关放一起、用户相关放一起、商品相关放一起。找订单代码时,不需要在多个目录之间来回切换。

什么时候该用 DDD

没有万金油的技术,DDD同样需要结合项目实际情况去判断是否需要使用。

适合 DDD 的场景:

  • 业务规则复杂、多变。比如电商系统的订单状态流转、金融系统的风控规则、ERP 系统的业务流程。
  • 需要长期维护和迭代。DDD 的前期设计成本较高,如果项目做一版就扔了,不值得投入。
  • 团队规模较大。多人协作时,清晰的领域边界能减少代码冲突和沟通成本。

不适合 DDD 的场景:

  • 简单 CRUD 系统。比如后台管理系统的增删改查,业务逻辑本身就很简单,用传统三层架构足够了。
  • 数据驱动型系统。比如数据分析平台,核心是数据处理和展示,不是业务规则。
  • 短期项目或原型验证。DDD 的设计成本在前期,短期项目用不上。

一个简单的判断标准是:当业务复杂度开始超过技术复杂度时,就可以考虑引入 DDD。

小结

DDD 的核心目标,是让代码结构与业务结构保持一致,把业务规则集中到领域模型中,而不是分散在各个技术层。它解决的是复杂业务带来的设计和维护问题,而不是性能优化或高并发问题。对于业务简单的系统,传统三层架构已经足够;但当业务不断演进、规则越来越复杂时,DDD 能帮助我们更清晰地组织代码,降低维护成本,也让团队协作更加顺畅。

不过,真正开始实践 DDD,并不是先设计实体、聚合这些战术模型,而是先理解业务、划分边界。只有明确了不同业务的职责范围,并建立统一的业务语言,后续的模型设计才有基础。下一篇,我们就来聊聊 DDD 战略设计中的两个核心概念:限界上下文(Bounded Context)和统一语言(Ubiquitous Language)。

相关推荐
BGK11235818 小时前
基于qemu_v8+optee 4.00 平台构建 ca/ta
java·大数据·数据库
何中应18 小时前
Spring Boot整合Doris
java·数据库·spring boot
笨笨饿19 小时前
101_详解USB协议
java·jvm·数据结构
J-Tony1119 小时前
【Redis】数据结构&&持久化
数据结构·数据库·redis
遨游DATA19 小时前
Maven dependencyManagement 已声明却仍缺 Jar:如何验证最终运行包
java·spring boot·maven·故障排查·依赖管理
腻害兔19 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 认证与权限:RBAC + 数据权限,这套“门禁系统“到底怎么设计的?
java·vue.js·人工智能·产品经理·ai编程
KaMeidebaby19 小时前
卡梅德生物技术快报|原核膜蛋白表达优化实操手册,膜蛋白的纯化梯度洗脱完整流程
前端·网络·数据库·人工智能·算法
Summer-Bright19 小时前
深度 | Agent 协议标准化:一场决定了 AI 经济底层规则的基础设施战争
java·数据库·人工智能·ai
我叫张小白。19 小时前
LangChain 结构化输出(Structured Output)技术文档
java·数据库·langchain