本篇要搞懂的 5 件事:从单体演进到微服务有哪几种打法、不同场景该怎么做领域建模、用 DDD 时常踩的几个坑、微服务设计要守的 4 条硬原则、真正动手拆微服务时除了业务还要看哪些非业务因素。
⚠️ 这是总结课——它不教新概念,而是把前 18 讲散落的方法论拧成一把"落地时的尺子",全是经验性的"该怎么选"。
承接前文:前面 18 讲把 DDD 从战略设计(划子域、限界上下文)一路讲到战术设计(聚合、实体、值对象、分层架构)。但作者点了一句很实在的话——理论再好,企业的发展历程、技术栈、团队文化都不一样,落地策略必然有差异。所以这一讲不再加新知识,而是回答一个工程问题:真到了要把单体改成微服务、要拆服务的时候,我该坚持哪些原则、避开哪些坑?
前 18 讲:DDD 怎么建模、怎么分层、怎么写代码
↓
19 讲(总结):落地时的取舍
├─ 怎么演进(绞杀 / 修缮 / 另起炉灶)
├─ 不同场景怎么建模(新建简单 / 新建复杂 / 单体遗留)
├─ 别踩的 4 个坑(别什么都用 DDD)
├─ 设计 4 原则(领域驱动、边界清晰、分层清晰、别过度拆)
└─ 拆分要看的 6 个因素(业务 + 非业务)
微服务的演进策略:单体怎么变微服务
从单体往微服务走,不是推倒重来一锤子买卖,作者给了三种打法,风险从低到高:
| 策略 | 怎么做 | 比喻 | 适合谁 |
|---|---|---|---|
| 绞杀者策略 | 在单体之外建新微服务,逐步把功能搬出去,新服务和老单体松耦合,时间一长老单体被"绞杀殆尽" | 建筑拆迁:先盖好新楼一部分,再拆旧楼一部分 | 想稳步替换整个老系统 |
| 修缮者策略 | 保持系统整体能力不变,只把有问题的局部(高性能、烂代码、发版频率不一致)剥出去做微服务 | 古建筑修复:哪里坏修哪里,外观功能不变,但质量提升 | 老系统大体能用,只想优化局部 |
| 另起炉灶 | 老系统照常跑(一般停新需求),新团队按原功能域重新建模、重写微服务,数据迁移后切换 | 推倒重做 | 作者不推荐大型核心系统这么干 |
💡 为什么作者不建议"另起炉灶"搞核心系统?因为重构后的不稳定、大量未知技术风险、新团队磨合,这些不确定性会让项目实施难度指数级上升。能小步改就别整个掀翻。
🪞 辅助理解:把单体系统想成一栋住了人的老楼。
绞杀者 = 在旁边盖新楼,住户一户户搬过去,最后拆掉老楼;
修缮者 = 不搬人,只把漏水的那间房单独翻新;
另起炉灶 = 让大家先凑合住着,另选块地重盖一栋一模一样的,盖好再整体搬——听着爽,但中途出任何岔子都是灾难。
不同场景下的领域建模策略
企业情况千差万别,建模也不能一个模子套。作者分三类场景:
1. 新建系统 · 简单领域
一个领域就是一个小子域,问题域小,直接上事件风暴建模即可,不用绕。
2. 新建系统 · 复杂领域
问题域太大,硬做一次性事件风暴会"工程量浩大、效果还不好"(比如"保险"得先拆成承保/理赔/收付费/再保,承保还得再拆投保、保单管理)。所以分三步走:
- 拆子域建模型:参考流程节点边界、功能聚合模块边界,结合领域专家把领域逐级拆到大小合适,再对每个子域做事件风暴,划聚合和限界上下文。
- 领域模型微调:把所有子域的模型摆一起,重点看聚合的重组,理清聚合边界、服务和事件之间的依赖,定稿。
- 微服务设计与拆分:按领域模型 + 拆分原则(下面第四节),落地成微服务。
3. 单体遗留系统
只想把局部(比如性能瓶颈模块)拆出去、其余保持单体。把要拆的那块当成一个简单子域,按上面"简单领域建模"走就行。注意要考虑新老系统的服务/业务兼容,**必要时引入防腐层(ACL)**做隔离转换。
💡 一句话抓住差异:域有多大决定要不要先拆。 小域直接建模,大域先逐级拆再建模,遗留系统则把要动的部分降维成一个小域来处理。
DDD 使用的 4 个误区(别为了 DDD 而 DDD)
这是全讲最"祛魅"的一节——作者反复强调 DDD 好,但不是万能锤。
| 误区 | 为什么是坑 | 正确姿势 |
|---|---|---|
| ① 所有领域都用 DDD | DDD 从战略到战术流程复杂,要养文化、要团队设计能力强;资源有限时全面铺开扛不住 | 先从富领域模型的核心域开始,别一上来全业务域推 |
| ② 全用 DDD 战术设计 | 聚合根 + 仓储擅长保证"新增/修改的数据一致性"(如订单总额=明细之和),但不擅长大数据量查询,还可能延迟加载拖效率 | 贫领域模型的活(统计、分析、报表)该用 SQL 就用 SQL,选最擅长该场景的方法 |
| ③ 重战术、轻战略 | 很多人学 DDD 只为写微服务,只盯战术。但战略设计产出的领域模型就是微服务的输入——边界划不清、对象定不明,微服务质量必差 | 战术要重视,战略更要重视(没有模型输入,DDD 微服务无从谈起) |
| ④ DDD 只适用于微服务 | DDD 比微服务早二十多年,"沉默"那些年一直用在单体设计里 | 吸取 DDD 的核心思想,结合业务和团队特点灵活用,单体也能用 |
🪞 辅助理解:DDD 就像一套很专业的木工电动工具。
钉个画框(简单业务/查询统计)用螺丝刀更快,非要搬出整套电锯电钻反而碍事。工具是为活儿服务的,不是为了显摆工具齐全。
微服务设计原则:要守的 4 条硬规矩
常见的高内聚低耦合、单一职责、复用这些就不重复了,作者单拎出来强调四条——每条都是"要 A 不要 B"的对仗句,特别好记:
| ✅ 要 | ❌ 不要 | 核心动作 | |
|---|---|---|---|
| 第一条 | 领域驱动设计 | 数据驱动 / 界面驱动 | 先建领域模型、定边界和领域对象,再拆服务;外部需求从外到内逐级消化,少冲击核心领域层 |
| 第二条 | 边界清晰的微服务 | 泥球小单体 | 聚合之间的领域服务和数据库实体杜绝相互依赖,靠应用层编排或事件驱动解耦,方便日后重组 |
| 第三条 | 职能清晰的分层 | 什么都往里塞的大箩筐 | 各层只依赖下一层(外调内、内逐层暴露,粒度由细到粗);应用层管编排别塞业务逻辑,领域层管核心逻辑;可复用能力向下沉淀 |
| 第四条 | 自己 hold 得住的微服务 | 过度拆分的微服务 | 拆太多 → 集成、运维、监控、定位成本全涨;没有云原生/DevOps/自动化监控能力就别硬拆 |
💡 第四条藏着一个特别解压的结论:只要前期按战略设计把逻辑边界划清、分层做好,“即使是单体也未尝不可”。 因为逻辑边界清晰,等团队能力上来了,“随时轻松重组出新微服务”,不费太多力气。所以别被"必须微服务"绑架——逻辑边界比物理拆分更重要。
微服务拆分要考虑哪些因素?业务 + 非业务
理论上"一个限界上下文 = 一个微服务",但限界上下文是纯业务视角划的,没考虑性能、安全、团队这些非业务因素——而这些恰恰对落地起决定作用。所以真拆的时候要综合看 6 个因素:
| # | 拆分因素 | 怎么用它指导拆分 |
|---|---|---|
| 1 | 基于领域模型 | 打底原则:围绕业务领域,按职责单一、功能完整来拆 |
| 2 | 基于需求变化频率 | 把**频繁变动(敏态)和相对稳定(稳态)**的业务分开,避免敏态频繁发版连累稳态 |
| 3 | 基于应用性能 | 把性能压力大的功能单独拆出去,免得它拖累别人、抢资源 |
| 4 | 基于组织架构和团队规模 | 拆分尽量别引发团队重组(增加沟通成本);单个微服务团队 10~12 人为宜 |
| 5 | 基于安全边界 | 有特殊安全要求的功能要从领域模型里独立出来,避免相互影响 |
| 6 | 基于技术异构 | 同一业务域内若技术栈差异大(.NET / Java / 大数据),可按技术边界拆 |
🪞 辅助理解:限界上下文给的是"理想的业务户型图",但真装修时还得看承重墙(性能)、防盗门(安全)、施工队人手(团队)、用什么材料(技术栈)。业务边界是起点,不是终点。
💡 第 5 条"基于安全边界"的意思是:把高敏感功能(认证、密钥、支付、合规审计)单独拆成微服务,本质是在系统层面做隔离、收缩风险面。
总结
这一讲是落地经验的"取舍清单",不背概念,记住四组判断:
- 演进怎么走:优先绞杀者(建新拆旧)或修缮者(局部翻新),大型核心系统别另起炉灶。
- 建模看场景:简单域直接事件风暴;复杂域先逐级拆再建模再设计(三步走);遗留系统把要动的部分当简单子域,必要时上防腐层。
- 别为 DDD 而 DDD:聚焦核心域、战术该用 SQL 就用 SQL、战略比战术更重要、单体也能用 DDD。
- 设计 4 原则 + 拆分 6 因素:领域驱动 / 边界清晰 / 分层清晰 / 别过度拆;业务边界打底,再叠加变化频率、性能、团队、安全、技术异构。
贯穿全篇的总纲就一句:把握好"边界"和"分层"两个大原则,其余一切以"快速高效解决实际问题"为准——逻辑边界划清了,物理上是不是微服务反而没那么重要。
一句话速记
演进别掀翻(绞杀/修缮优先)、建模看大小(复杂先拆再建模)、别为 DDD 而 DDD(聚焦核心域、战略重于战术)、设计守 4 条(领域驱动·边界清晰·分层清晰·别过拆)、拆分看 6 因素(业务打底,再叠加变化频率/性能/团队/安全/技术异构)。
思考题
你是"架构自己设计、代码靠 AI 代写"的模式,那么:
- 拿你正在做的 MemoryEngine(或任意一个练手系统)来套:按这 6 个维度看,哪块功能值得单独拆出去?拆完是真的解耦了,还是只是搬了个家?
- 第四条说"逻辑边界清晰的话,单体也未尝不可"。你现在的项目有必要拆微服务吗?还是先把分层和限界上下文在单体里划清楚,等真需要了再让 AI 帮你重组?
- 误区②说"贫领域模型的查询/统计该用 SQL 就用 SQL"。让 AI 帮你写代码时,你会不会因为’在学 DDD’就强行让它把简单查询也套上聚合根+仓储?怎么给 AI 下指令,才能让它"该用 DDD 用 DDD、该用裸 SQL 用裸 SQL",而不是一刀切?
