DDD是个什么鬼?一个老架构师的吐槽
2025-12-24
前言
做了十几年架构师,见过的项目不下百个,踩过的坑能绕地球三圈。最近几年,DDD(领域驱动设计)这玩意儿火得一塌糊涂,到处都是布道师在吹,仿佛不用DDD就不是好架构师似的。
说实话,我一开始也被忽悠得一愣一愣的,买书、听课、实践,折腾了好久。但越用越觉得不对劲,最后发现:这玩意儿就是个坑,而且是个深坑。今天就来好好聊聊为什么我觉得DDD是个大忽悠。
DDD到底在玩什么花样?
概念多得让人头大
你以为学个设计模式23个就够多了?DDD告诉你:那算什么,我有一大堆概念等着你:
聚合根(Aggregate Root)
值对象(Value Object)
领域服务(Domain Service)
应用服务(Application Service)
仓储(Repository)
工厂(Factory)
领域事件(Domain Event)
...
我去,这么多概念,光是理解就要花老长时间。更要命的是,这些概念的边界模糊得要死。
拿聚合根来说,什么时候该用?边界怎么划?问十个DDD专家能给你十一种答案。我见过为了划分一个用户聚合,团队开会讨论了三天,最后还是没个定论。这不是扯淡吗?
学习成本高得离谱
想学好DDD,你得具备:
深厚的面向对象功底(大部分人连这个都没有)
丰富的业务理解能力(这个更稀缺)
抽象思维能力(天赋要求)
大量实践经验(时间成本)
问题是,现在大部分程序员连基本的面向对象都没搞明白,继承、封装、多态用得乱七八糟,你让他们去理解DDD这套高深理论?纯粹是赶鸭子上架。
我见过太多团队,架构师画了一大堆UML图,定义了一堆领域模型,下面的开发看得云里雾里,最后还是按照老方法写增删改查,只是套了层DDD的壳子。
我们真正的问题在哪里?
面向对象用得稀烂
说句不好听的,国内大部分程序员的面向对象水平还停留在十年前。我经常看到这样的代码:
// 这样的"面向对象"代码随处可见
public class UserService {
public void processUser(User user) {
if (user.getType().equals("VIP")) {
// 一大堆VIP逻辑
} else if (user.getType().equals("NORMAL")) {
// 一大堆普通用户逻辑
} else if (user.getType().equals("PREMIUM")) {
// 又是一大堆逻辑
}
// ... 还有更多if-else
}
}
这哪是面向对象?这就是用Java语法写面向过程的代码!多态在哪里?职责分离在哪里?
建模思维缺失
更要命的是,大家根本不知道什么叫建模。我问过很多开发:
"你为什么要创建这个类?" "呃...因为需求文档里有这个实体"
"这个方法为什么放在这个类里?" "呃...感觉应该放这里"
完全没有从问题域的角度思考,没有考虑对象的职责和协作关系,纯粹是拍脑袋决定。
DDD不但没解决问题,还把水搅浑了
治标不治本
面向对象用得稀烂,建模思维缺失,这些是根本问题。DDD呢?它不去解决这些根本问题,反而在上面又盖了一层更复杂的理论。
就好比一个人连走路都没学会,你却要教他跳芭蕾舞。结果可想而知。
我见过无数项目,团队成员对面向对象的基本原则都搞不清楚,却要按照DDD的方式来组织代码。结果就是:
代码层次多得要命
抽象层次混乱
职责分配不清
接口设计混乱
过度设计成了家常便饭
DDD最大的副作用就是让程序员觉得不搞几层抽象就显得不专业。我见过为了处理一个简单的用户注册功能,搞出来十几个类的:
UserRegistrationDomainService
UserRegistrationApplicationService
UserRegistrationFactory
UserRegistrationRepository
UserRegistrationValidator
UserRegistrationSpecification
...
我去,注册个用户而已,至于搞这么复杂吗?这不是设计,这是炫技!
实战中的血泪教训
项目A:电商平台的噩梦
去年接手了一个电商项目,前任架构师是个DDD狂热分子。整个项目严格按照DDD来设计:
订单聚合包含17个类
商品聚合包含21个类
用户聚合包含13个类
各种领域服务、应用服务、仓储满天飞
看起来很专业对吧?实际用起来呢?
改个简单功能要动七八个文件
新人看代码要跟迷宫一样
性能问题一大堆(因为抽象层次太多)
测试写起来要死要活
最后我花了三个月时间重构,把那些华而不实的抽象都砍掉,项目终于能正常运行了。
项目B:简单业务的复杂化
还有个更典型的例子,一个简单的内容管理系统,核心就是增删改查文章。结果架构师非要用DDD:
Article聚合根
ArticleContent值对象
ArticleTitle值对象
ArticleStatus值对象
ArticleDomainService
ArticleApplicationService
ArticleRepository
ArticleFactory
ArticleSpecification
我算了一下,为了实现一个简单的发布文章功能,需要创建9个类,写200多行代码。如果用传统方法,一个Service + 一个Entity就搞定,最多50行代码。
这是进步还是倒退?
什么才是正道?
先把基本功练扎实
与其折腾什么DDD,不如先把面向对象的基本功练扎实:
单一职责原则:一个类只做一件事,别什么都往里面塞 开闭原则:要扩展功能,加新类,别改老代码 里氏替换原则:子类要能完全替代父类,别搞奇怪的继承 接口隔离原则:接口要小而精,别搞大而全的上帝接口 依赖倒置原则:依赖抽象,不要依赖具体实现
这些原则看起来简单,真正理解并应用好,需要大量实践。把这些基本功练扎实了,比学一百个DDD概念都有用。
从简单开始,循序渐进
建模能力不是一天两天能培养出来的,得慢慢来:
先从简单业务开始:别上来就搞复杂系统,从简单的CRUD开始
关注对象职责:这个类应该负责什么?不应该负责什么?
重视接口设计:接口要稳定、易用,内部实现随便你怎么改
多实践,多反思:每个项目结束后,回头看看哪些设计是好的,哪些是坑
保持务实的态度
软件设计的目标是解决实际问题,不是炫技。好的设计应该是:
简单直观:新人能快速理解
易于维护:改功能不用动一大堆代码
性能合理:别为了抽象牺牲性能
符合业务:贴近实际业务场景
如果一个设计需要花大量时间向团队解释,那多半是过度设计了。
总结
DDD本身可能有些价值,但被过度神化了。对于大多数团队来说,与其花时间学习这些高深理论,不如踏踏实实把面向对象的基本功练好。
记住一句话:简单有效的设计胜过复杂炫酷的架构。别被那些高大上的概念忽悠了,实用主义才是王道。
作为架构师,我们的职责是让系统更简单、更稳定、更易维护,而不是显摆自己知道多少理论概念。DDD这种增加复杂度却不解决根本问题的东西,还是算了吧。
最后送给大家一句话:Less is More。简单的才是最好的。