聊城市网站建设_网站建设公司_测试工程师_seo优化
2026/1/10 0:28:31 网站建设 项目流程

这不是一篇 DDD 教程,也不是最佳实践指南。

这是我在真实项目中尝试使用 DDD 之后的困惑、挣扎,甚至是放弃。

如果你正在考虑要不要上 DDD,

或者你已经在用,但总觉得哪里不对劲,

那这篇文章,可能会戳中你。

-01-

DDD 第一个让我崩溃的点

CQRS 分类,现实世界根本不配合

DDD + CQRS 的世界里,所有操作都应该被清晰地分成三类:

  • Command:只负责“改状态”,不关心返回值

  • Query:只读、幂等、轻量

  • Event:对“已经发生的事情”的被动响应

听起来很优雅,对吧?

但现实是:大量操作,三个都不是。

一个真实到不能再真实的例子

我们做了一个「服务调用系统」,用户通过 API 调用第三方服务:

POST /api/service-invoke-requests

{
"serviceId":"weather-api",
"inputData":{
"city":"Beijing"
}
}

同步返回结果:

{
"requestId":"req-123",
"status":"SUCCESS",
"outputData":{
"temperature":"25°C",
"weather":"Sunny"
}
}

现在问题来了——
这到底是 Command?Query?还是 Event?

它是 Command 吗?

  • Command 理论上应该只返回 id / status

  • 但这里要返回完整的业务结果

  • 而且它本质上是“读取用户配置 + 调用外部服务”

不符合。

那是 Query 吗?

  • Query 应该是只读、轻量、幂等

  • 但这个接口可能扣费、发短信

  • 可能执行几秒甚至更久

还是不符合。

Event?

  • Event 是“事情发生之后”的通知

  • 这是用户主动发起的请求

也不是。

结果:三个都不是

你会发现,现实系统里有大量这样的操作:

操作

改状态

返回数据

同步

CQRS 分类

用户注册

Command

查询用户列表

Query

调用第三方服务

生成报表

AI 生成内容

灰色地带,才是主流。

我的真实感受

  • 很多操作既改状态,又要返回复杂数据

  • 不同人对 CQRS 定义理解完全不同

  • Code Review 经常变成:

    “这个到底算 Command 还是 Query?”

最后发现:
争论半天,对业务毫无价值。

所以我后来干脆:

// 与其纠结
CreateUserCommand
QueryUserByIdQuery

// 不如实用
CreateUserRequest
GetUserByIdRequest

不“纯粹”,但省时间、不内耗、能交付

-02-

第二个让我放弃 DDD 的点

聚合根边界,真的太难判断

DDD 说:

聚合根是事务一致性的边界。

听起来很清晰,直到你真的开始建模。

一个让我纠结了很久的例子:收藏功能

用户收藏文章,看起来简单得不能再简单。

但你一旦开始用 DDD 思考,马上陷入泥潭:

  • 收藏属于User

  • 还是属于Article

  • 还是一个独立的聚合根

从不同视角看,结论完全相反

从用户角度:

  • 收藏是“我的收藏”

  • 用户删了,收藏要不要删?不一定

像 User 的一部分,又不完全是。

从文章角度:

  • 收藏影响文章的收藏数

  • 文章删了,收藏要不要删?也不一定

像 Article 的一部分,又不完全是。

从行为角度:

  • 有 ID

  • 有创建时间

  • 可单独查询

看起来像独立实体。

但换个现实角度:

它不就是一张多对多中间表吗?

用 DDD 理论去“严格推导”,只会更混乱

  • 一致性边界?
    → 收藏根本不需要强一致

  • 事务边界?
    → 收藏数完全可以异步更新

  • 生命周期?
    → 依附谁都不完全合理

最后你会发现:

是否是聚合根,取决于你打算以后怎么玩这个功能。

而不是 DDD 给你的某个“明确规则”。

我的结论

  • 同一个功能

  • 不同阶段

  • 不同团队

建模方式完全不同。

而 DDD 给你的,是一堆“看起来有道理,但无法落地的判断标准”。


-03-

最致命的一点

DDD 和性能优化,是天然对立的

这是我真正放弃 DDD 的原因。

真实问题:User 表太大,必须拆表

  • 1000 万用户

  • 80% 查询只要 username / email

  • 表里却有一堆 TEXT / JSON 大字段

拆表后,性能立竿见影。

但 DDD 告诉你什么?

User 是聚合根,Repository 应该返回完整 User

于是你陷入死循环:

  • 返回完整聚合 → 性能差

  • 按需加载 → 破坏聚合完整性

  • 懒加载 → N+1 查询地狱

  • 多粒度查询 → User 对象时完整、时残缺

你写的每一行代码,都在DDD 理论和性能现实之间妥协

本质矛盾

  • DDD 假设:加载完整聚合不是问题

  • 现实世界:性能才是第一约束

这个矛盾,无解

-04-

最后一个现实问题

DDD 太花时间了

  • 建模时间是 CRUD 的 2~3 倍

  • 需求却随时可能被砍、被改、被推翻

  • 团队对 DDD 理解不一致,沟通成本极高

很多时候你会发现:

还没来得及体现 DDD 的价值,需求已经变了。

-05-

总结

最后想说的几句大实话

1. 大多数项目,根本不需要完整 DDD

  • 80% 的系统就是 CRUD

  • 强行 DDD,只会增加复杂度

2. DDD 的思想是对的,但方法已经老了

  • 关注业务语言

  • 领域拆分思路

  • 教条式建模

3. 现实中的 DDD,都是“DDD 风格”

  • Command 返回业务数据

  • 查询直接写 SQL

  • 为性能破坏聚合完整性

我们用的是DDD 的外壳,而不是 DDD 本身

DDD 不是银弹。
真正的问题,是错把它当成教条,而不是工具

没有完美的架构,只有合适的架构。

https://mp.weixin.qq.com/s/YurPZEv-vKRjA2LtnDmNlw

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询