news 2026/10/24 8:40:27

DDD的“岁月史书”:警惕那些“本来应该”的伪定义

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DDD的“岁月史书”:警惕那些“本来应该”的伪定义

最近我在几个技术群和博客评论区里,看到了一波很有意思的“回头翻案”式言论。有人翻出十二年前的帖子,说“DDD本来就是给遗留系统改造用的,你们拿来设计新系统是误用”;有人说“DDD根本不是什么建模方法,它只是分层架构的别名”;还有人信誓旦旦地讲“真正的DDD必须用六边形架构,不然就是假DDD”。这种叙述方式,放在别的圈子里叫“岁月史书”,放在技术圈子里就是有人开始按自己的需要,重新编排领域驱动设计(DDD)的“正史”了。

作为一个从敏捷开发火热年代就开始接触DDD、也亲手在几个中大型项目里落地过领域模型的从业者,我想认真聊聊这件事。不是说不能批评DDD,恰恰相反,DDD身上有很多值得反思的问题:概念门槛高、落地成本大、团队认知参差、被工程化包装后面目全非……这些都该骂。但“该骂”和“捏造历史”是两回事。当讨论变成罗生门,新手很容易被带偏,甚至带着错误的认知去设计系统,最后把失败归结为“DDD不行”。这篇文章我不打算站队,只想把几件我自己踩过坑、查过资料、见过真实案例的事情摊开讲清楚,帮大家在这波“岁月史书”的声浪里,找到一条能落地的判断路径。

1. 先盘点一下:这波“翻案”里都有哪些典型言论

1.1 “DDD已死”和“DDD从未活过”

每隔几年,技术社区就会周期性出现“DDD已死”的论调。这个调调我见得很多了,从2015年左右微服务刚火起来时被拿出来说一次,到这几年的“云原生时代DDD过时了”,套路几乎一模一样:先找一个失败的团队案例,再引用几段被截断的原书内容,最后得出“DDD只能活在PPT里”的结论。

最近的新玩法更进了一步,直接“釜底抽薪”:“DDD其实从来就不是一个具体的方法论,它只是一堆概念的拼凑”。这种说法最难反驳,因为它听起来很有“独立思考”的气质,符合人们对“祛魅”的喜好。可问题是,如果《领域驱动设计》那本书里那套关于模型、通用语言、限界上下文、聚合的理论不是方法论,那什么才算方法论?难道方法论必须要到“代码生成器”那个粒度才配叫方法论?

我倒不反对对DDD做“降格”处理——把它看作一套思维工具而不是银弹,这恰恰是健康的。但“DISS不是问题,否定其历史是另一个问题”。当一个人说“DDD从未活过”时,他不是在参与技术讨论,而是在做话语权的重置——因为他无法说服你DDD不好,那就干脆让“DDD曾经被误解为很好”这件事本身变成笑话。

1.2 “DDD本来就应该xxx”的重新发明

比“已死论”更普遍的,是各种“本来论”。典型句式是:“DDD本来就应该配合事件溯源使用”“DDD本来就应该用六边形架构落地”“DDD本来就是要做CQRS的”……

这种话术的高明之处在于,它不否定DDD,而是把你的实践经验全部判为“不入流”。比如你做了几年DDD,用的还是经典的四层架构+共享内核,突然有人告诉你“没有用六边形架构的DDD不是真正的DDD”,你心里是什么感觉?你会先怀疑自己,然后怀疑自己的项目,最后怀疑那本书。

但“本来论”最大的问题,是缺乏文本依据。Eric Evans在《领域驱动设计》里通篇没有把DDD和任何一种具体架构风格绑定。他讲的架构,是“模型驱动设计”下各层如何协作、如何保护领域层不被技术细节污染,而不是“必须用端口适配器”这种具体处方。后者是后来无数实践者从工程教训中总结出的偏好,把它们说成“DDD的定义”,就是把实践经验偷偷升级成了教义。

这种重新发明还有个副产品:术语通胀。什么都可以叫DDD,什么都可以说成“DDD的应有之义”。当所有人的DDD都不是同一个东西时,圈子里的讨论就失去了公共基础。于是真正想学习DDD的人,比算法工程师学新框架还累——因为框架文档是明确的,DDD却没有“官方文档”,只有一堆互相打架的二手解读。

1.3 “用DDD失败的人,都是没用对”

还有一类言论,我觉得要单独拎出来说。它诞生于“翻案”的反面,走的是“原教旨主义”路线:只要有人公开说DDD项目失败了,评论区必然会出现“你们根本不懂DDD,伪DDD当然会失败”。

这套逻辑几乎是不可证伪的。它把所有失败都归咎于“没有用正宗DDD”,但“正宗”的定义永远掌握在评论者手里。你说你做了事件风暴,他说你没做领域分析;你说你做了领域分析,他说你的聚合设计是错的;你问哪里错了,他开始讲“这个需要长期咨询陪跑”。这种逻辑本质上和“岁月史书”是一枚硬币的两面:都在用叙事替代事实,用定义权替代证据。

我见过真实的DDD失败案例,也做过复盘,失败的原因通常非常复杂:组织架构与限界上下文冲突、领域专家缺席、团队代码能力不足、业务本身就在剧烈变化……把这些统统推导到“因为没学正宗DDD”上,既不符合事实,也不负责任。

2. 六边形架构是怎么被“焊死”在DDD战车上的

2.1 六边形架构的真正生日

既然热词里带着六边形架构,那这大概就是最近“岁月史书”事件的重点战场了。先把历史事实摆出来:六边形架构(Hexagonal Architecture)也叫端口与适配器架构,是Alistair Cockburn在2005年前后提出的,起因是他在实践中发现,业务逻辑不该被数据库、UI、消息队列这些外围技术绑架。

那个年代还没有“微服务”这个词,DDD蓝皮书刚刚出版两年,两者是完全独立的思想脉络。六边形架构早期最知名的实践者是写《企业应用架构模式》的Martin Fowler那一派,他们当时在讨论“业务逻辑与技术细节分离”时,引用的是《企业架构模式》中的“Application Facade”和“Domain Model”,和Evans的DDD并没有强绑定关系。

那问题来了:为什么现在一说DDD,默认配图就是那个经典的“六边形+内部领域模型+外部端口”的图?这就要说到DDD落地史上的一个尴尬事实:Evans在书里提出的经典四层架构(用户界面层、应用层、领域层、基础设施层),在实际工程中非常难拿捏。尤其是“基础设施层依赖方向倒置”这个点,大多数人做不到,一做就做成“Controller调Service调Repository”,领域层变成一堆贫血对象的文件夹。

2.2 当“分层”撑不住时,六边形被当成了救生圈

我在第一个真正规模比较大的DDD项目里,就踩过四层架构的坑。当时我们严格按照书里的分层做了包结构,controller、service、domain、infrastructure分得清清楚楚,代码评审时大家都很满意。但等业务复杂起来,问题立刻浮现:一个应用服务经常需要编排多个仓储,事务边界落在哪一层?消息发不出去要不要回滚?外部API调用超时,领域事件到底算不算已发布?

这些问题四层架构没有明确答案,团队开始各自为政。后来我们引入了六边形架构的思路——把入口和出口都抽象成端口,把数据库、消息队列、HTTP客户端都当作适配器替换。这么一改,领域层干净了不少,测试也变得好写了。那段时间我们确实在内部达成了共识:“DDD项目就该这么搭”。

但这里有个重要的认知陷阱:我们是“因为DDD遇到了工程问题,所以选择了六边形架构来辅助”,而不是“六边形架构是DDD的前提”。可多数博客在传播时,把第二个表述当成了事实。于是“DDD+六边形”从“经验组合”变成了“标准范式”,最后升级为“不用六边形就不算DDD”。这本质上就是一次典型的术语漂移事件。

2.3 捆绑叙事为什么这么有市场

我后来想明白了,这种捆绑叙事有它不可抵挡的传播优势:它给了学习者一个“标准答案”。

DDD最让人痛苦的地方就是“答案全靠自己悟”。限界上下文怎么划?聚合怎么做大做小?这些没有唯一正确的解,让习惯了框架文档的工程师非常没有安全感。六边形架构恰好提供了一种“看起来有标准”的结构:端口、适配器、内部六边形,边界清晰,目录结构一目了然。当有人说“这就是DDD的标准落地方式”时,很多人会本能地选择相信——因为相信让自己舒服。

然而,标准答案的代价是牺牲灵活性。六边形架构本质上解决的是“技术细节与业务核心的隔离问题”,它根本不关心你的领域模型质量。一个完全没有领域模型的CRUD项目,照样可以用六边形架构套得严丝合缝。反过来,一个领域模型极其精妙、但采用传统三层架构的项目,也不会因为没用六边形就失去“DDD资格”。把两者焊死,对双方都是伤害。

我个人的结论是:你可以把六边形架构和DDD配合使用,这没有错,现实中也确实很好用;但你应该清楚,你是在“用DDD建模,再用六边形架构做代码组织”,不是在做“标准DDD”。放弃“标准答案”的执念,反而更容易用好这两样东西。

3. 翻开蓝皮书:那些正在被悄悄掉包的“原厂定义”

3.1 “通用语言”不是词汇表,是协作协议

“岁月史书”最精细的操作,就是把原书概念掉包成另一个看似相似、实际完全不同的东西。“通用语言(Ubiquitous Language)”就是重灾区。

流行解读里,通用语言被简化成了一张“团队术语表”:业务管订单叫“工单”,技术管它叫“Order”,大家统一一下,就叫“Order”吧。表面看这就是通用语言的全部。但Evans写这个概念的时候,强调的是在一个限界上下文内,业务专家与开发人员使用同一套语言进行讨论、建模、设计,而且这套语言必须体现在代码、测试、文档、日常对话中。

被简化成词汇表之后,通用语言的核心动作——深入的、能暴露模型分歧的对话——被完全丢掉了。团队可能拥有一份术语表,但做需求分析时依旧各说各话,建出来的模型跟业务真实心智模型严重背离。这是一种特别隐蔽的“岁月史书”:它没有篡改文字,却篡改了概念的生命力。

3.2 “模型”不是只画UML,是要进入代码的

第二个被掉包的概念是“模型”。好多翻案文章喜欢嘲讽DDD——“画一堆UML图就能解决复杂业务吗?”这个靶子很好打,因为确实有很多伪DDD项目热衷于画图。

但原书的立场恰恰相反。Evans反复强调,模型必须“和实现绑定”,要让它成为“软件的脊柱”。一个只存在于PPT里的抽象模型,在他看来不是DDD的成果,而是失败。他在前言里就写得很明白,这本书讲的是“如何在软件中建立模型”,而不是“如何画好一张模型图”。可惜的是,太多实践者(以及批评者)把“建立模型”理解成了“绘制模型”。

这也解释了为什么有些“翻案”看起来很犀利——他们批判的对象本身就不是DDD,而是伪DDD。但他们偏要沿着“伪DDD就是DDD”这条线去完成对DDD的宣判,这就把批判做成了新的历史叙事。

3.3 贫血模型与充血模型:被夸大的对立

讨论DDD永远绕不开“贫血模型vs充血模型”,而这场讨论里也充斥着我见过最多的掉包。流行观点是:DDD推崇充血模型,使用贫血模型就是没有领会DDD精神,甚至“贫血模型是一种反模式”。

这个观点源自有据。Martin Fowler写过一篇著名的《AnemicDomainModel》,批评了那种“对象只有getter/setter,业务逻辑全散落在Service里”的贫血模型。这篇博客对DDD圈影响极大。但这里有个细节被岁月史书淹没了:Evans在他的书里并没有明确批判贫血模型,他讲的是“模型承载业务规则”这个原则。如果一个贫血模型配合服务层,仍然能让业务规则的语义清晰可见、由领域层统一表达,那它并不必然违背DDD。

现实情况是,很多项目因为团队的代码能力、业务规模、历史包袱,用“贫血对象+事务脚本”的方式反而更清晰。你可以说这不是DDD的最理想形态,但把它直接打成“异端”,等于把原书没有的教义塞进了历史。

3.4 战略设计为何总是缺席

最后想认真提一句:所有翻案声音里,很少听到有人认真讨论战略设计。“限界上下文”“上下文映射”“防腐层”“共享内核”“开放主机服务”这些属于Evans原书后半部分的内容,才是DDD相对其他建模方法最有价值的部分——它试图解决“多模型共存”“系统边界”的问题。

但战术设计(聚合、值对象、领域事件、仓储)因为更贴近编码,成了培训机构的卖点、博客的流量入口。狼来了喊多了,“DDD=建聚合+画领域事件图”的矮化版本反而成了主流。这变成了一种双重的岁月史书:一边是战术设计被拔高成全部,一边是战略设计的缺席被默认为正常。等到有人说“DDD解决不了系统边界问题”时,你甚至不知道他说的“DDD”到底是指原书里的DDD,还是那个被矮化过的DDD。

4. 假DDD泛滥,才是岁月史书真正的土壤

4.1 “建文件夹”式DDD:最流行的实践幻觉

这几年的项目里,我见过特别多的“DDD项目”,说它们是“建文件夹”式DDD一点都不冤枉。它们的特征是:包结构严谨地按照application/domain/infrastructure三层划分,领域层里躺着一堆实体和一些表面上的值对象,然后就没有然后了。

聚合内没有业务不变量,领域事件量是零,规则散落在应用服务里,所谓“领域服务”只是替Controller分担了十行代码。遇到这种项目,团队复盘时会觉得惊讶:“我们严格按照DDD做的,为什么代码还是烂?”项目最终失败,团队把责任推给DDD。

但这里面有个特别反直觉的真相:DDD的许多概念,确实是“听着简单、做着极难”的。我自己的团队第一次做聚合划分时,信心满满地划分了十几个聚合,结果两个月后就发现了模型漂移——同一个业务规则在两个聚合中各实现了一版。如果你没有经历这种“被模型教训”的过程,你很难说自己在实践DDD。

4.2 失败复盘里的归因错误

当大量“建文件夹式DDD项目”失败后,翻案文章就有了现成的素材。它们会把这些失败的复盘当作“DDD项目的失败”,进而推导“DDD不适用于xxx场景”。但稍微仔细看一眼就能发现,那些项目里根本没有像样的领域建模过程——没有事件风暴级别的业务探索,没有核心域和支撑域的区分,没有限界上下文的独立演进。

这种归因错位很有意思:一个人开车,路线图拿反了,车子半路抛锚,他不怪自己没检查油量、不怪自己看错地图,而是得出结论“这条路根本不通,网上那些说这条路能到的人都是在骗人”。然后他开始写帖子,把这条路的真实地理坐标全部“修正”一遍。这就是岁月史书的生成机制:不是历史本身被歪曲,而是提取历史样本的过程充满了偏差。

4.3 伪DDD为什么会成为主流叙事

我不愿意把所有锅都扣在培训机构和自媒体头上,因为需求是双向的。学习者在面对复杂业务时,确实需要一套能快速上手的“骨架”,而“DDD就是用六边形架构+建四个文件夹”这个骨架,是市面上最容易理解的简化版。它牺牲了DDD最有价值的“模型驱动”内核,保留了最容易展示的外壳。

但这种简化一旦形成生态,就会被大家默认为“DDD的事实标准”。等有一天原教旨主义者站出来说“你们这些根本不是DDD”,双方就会开始互抛历史。一边说“DDD本来就是这样教的”,一边说“DDD从来不是这样定义的”。吵到最后,没有人去翻开那本书,没有人去看真实项目的演进,只剩“谁的话术更像权威”。

这也是为什么我觉得“岁月史书”这个现象,本质上并不是恶意造谣,而是技术传播中“简化-固化-神圣化”的必经之路。警惕它,是因为它会污染你独立判断的参照系。

5. 面对岁月史书,一个实践者的自处方式

5.1 观点是廉价的,文本是硬锚点

碰到任何关于“DDD本来应该怎样”的说法,我的第一反应就是:你说的“本来”,出处在哪?

Eric Evans的《领域设计》是第一手文本,Vaughn Vernon的《实现领域驱动设计》是优质的扩展读物,Alberto Brandolini的事件风暴方法论和Greg Young的CQRS/ES,都是后来被实践证明有效的补充,但它们有各自的文献出处和语境。当你发现一个人把上述所有来源都混在一起说成“DDD本来如此”时,你就该知道,这是一锅被人为搅匀的史书,而不是一本有章节页码的科学著作。

这里分享一个特别实用的技巧:给自己建一张“概念出处表”。同样是“聚合”,Evans怎么说、Vernon怎么扩展、你在项目中怎么落地,各占一列。当你读到一篇新博客时,把它的观点放到表格里对照,很快就能看出作者是在转述原书、还是在补充个人经验、还是在创造“传统”。这个方法不复杂,但能过滤掉绝大多数只有情绪没有依据的翻案文。

5.2 识别“岁月史书”话术的三个红旗

  • 红旗一:绝对化定义。只要出现“真正的DDD必须……”“DDD本质上就是……”这类句式,先警惕。定义权是历史叙事权的浓缩,一个健康的术语讨论应该是“在xxx语境下,我认为比较好的一种落地方式是……”。
  • 红旗二:动机可疑的归因。“只要用了DDD就是失败”“只有用了DDD才配叫复杂业务架构”,两种极端都值得怀疑。技术决策是多因素博弈的结果,任何单一归因都可能是为了叙事服务的。
  • 红旗三:凭空消失的失败细节。翻案文章往往把失败项目的关键细节处理得很模糊:团队规模、领域复杂度、业务语言统一程度、技术团队能力基线,这些信息要么缺失,要么被严重简化。这些细节才是复盘的灵魂,删掉它们,故事就开始变成史书。

5.3 把DDD和它的合作伙伴解耦,反而更好用

我想把“DDD、六边形架构、CQRS/ES、微服务”这几个常常被焊死的概念拆开来,它们之间是“可以协作”的关系,不是“必须配套”的关系:

概念解决的问题与DDD的关系
DDD业务复杂性建模与模型落地核心方法论
六边形架构技术边界隔离与技术细节解耦可选实现风格
CQRS/ES高并发读写分离与溯源审计可选的读写模型策略
微服务部署独立性与组织自治战略设计的一种落地载体

我自己在项目中就做过非六边形的DDD落地方案,也见过CQRS跟DDD毫无关系的纯数据平台项目。解耦后,每个概念各自承担职责,反而更容易判断:业务建模累了,问题出在DDD的战术设计;边界层依赖混乱了,去调整六边形架构的端口;性能扛不住了,再考虑CQRS。如果所有问题都记在“DDD”帐上,你既解决不了问题,也对不起DDD。

5.4 我的建议:去写自己的“战场记录”,而不是参与“历史定稿”

防“岁月史书”最好的方式,不是你成为一个更会吵架的评论者,而是成为一个勇于公开细节的实践者。我在团队内部推行过一个很小的做法:每个迭代结束时,在技术周报里花两三百字记录“模型在这个迭代发生了什么变化”——聚合是否拆分、限界上下文之间是否新增了合作方式、哪些通用语言的词汇在实践中被替换了。

这些记录弥足珍贵,因为它们记载的是“模型与真实业务的反复对冲”,而不是某篇文章里那个光滑圆润的“最佳实践”。当团队后来面临架构质疑时,我们不需要引用任何权威文章,只需要把这些记录摊开,就能说清楚“这个设计决定是怎么来的,当时面对什么约束,后来效果如何”。这就是你自己的“正史”。

说到底,DDD最大的敌人从来不是所谓的“新范式”,而是那些为了获得确定性而强行收编历史的声音。一个领域、一种方法论,只有允许不同经验共存、允许失败细节被讨论、允许文本解释被挑战,它才可能真正活下来。我不指望能帮谁画出一条绝对正确的DDD路线,但如果这篇东西能让你在下一次听到“DDD本来应该……”的时候,多问一句“这句话的出处在哪里、这位作者的上下文是什么”,那它就没白写。

方法论一旦被神圣化,就会开始腐朽。保持一点考古学家的怀疑精神,对DDD、对六边形架构、对所有被包装成“正统”的东西,都保持一点距离,反而能走得更远。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/24 8:39:55

企业级疫苗预约系统落地实践:SpringBoot+Vue+MyBatis+MySQL

企业级疫苗发布与接种预约系统的落地实践做这个项目之前,我被疫苗预约这个场景折磨过一阵子。社区卫生院的朋友跟我吐槽,每到流感季或者新疫苗到货,电话被打爆、现场排长队、库存对不上,光靠Excel登记根本撑不住。聊完我就明白&am…

作者头像 李华
网站建设 2026/10/24 8:39:44

VDC是什么?一文读懂虚拟设计与施工和虚拟数据中心

第一次见到VDC这个词的人,多半是带着问号搜进来的。这个词在两类完全不同的圈子里都能看到:建筑工地和IT机房。在施工项目的例会纪要里,它是Virtual Design and Construction(虚拟设计与施工)的缩写;在云服…

作者头像 李华
网站建设 2026/10/14 13:21:56

二分查找与搜索插入位置:循环不变量与边界条件全解析

作为一个常年跟数组、查找、排序打交道的程序员,我刷题和写业务代码时最常被问起的一个算法就是二分查找。尤其是"搜索插入位置"这类题,看似基础,却是我面试候选人和带新人时最愿意用的试金石——因为它能精准暴露一个人对循环不变…

作者头像 李华
网站建设 2026/10/14 13:22:40

Android滚动视图深度实战:ScrollView嵌套、事件冲突与性能优化

1. 滚动视图是什么,为什么现在还要写它 做Android的都应该清楚,滚动视图这事,说简单是真简单,布局里套个ScrollView,内容一多就能滑了。但说复杂也复杂,横向加纵向一起嵌套、跟ViewPager抢手势、列表数据大…

作者头像 李华
网站建设 2026/10/14 13:22:40

t3code:以可复用片段为核心的代码沉淀工作流

先说个事:我给自己的编码习惯起了个名字,叫 t3code。听起来像个开源项目代号,其实它就是一套我反复调整大半年、从无数次返工中总结出来的个人代码工作流:先想透、快速试、持续沉淀,然后把每一次真正有效的代码变成可复…

作者头像 李华
网站建设 2026/10/14 13:21:31

小动物救助领养系统实战:ThinkPHP+Laravel双框架与微信小程序开发

做过的业务系统里,小动物救助领养系统算是一个让我印象很深的项目。接这个需求时,我下意识觉得“这不就是个二手交易平台换层皮嘛”,但真和救助站、动保组织的负责人聊完业务流程后,我才发现这套系统的麻烦程度一点不比电商低&…

作者头像 李华