别急着改代码先画子域地图再动第一行这是「DDD 实战系列」的第 2 篇。第 1 篇我们聊了业务规则要有唯一的家解决了模型内部怎么写。这一篇往上抬一层在写任何模型之前业务这块大版图到底该从哪下刀一、先回答一个问题如果现在让你负责的那套系统砍掉一半功能你先砍哪一半我拿这个问题问过不少团队大多数人会愣一下。不是因为舍不得而是脑子里没有一张地图——一张哪些业务是企业赚钱的命根子、哪些只是配套、哪些其实谁家都一样的地图。这正是 DDD 战略设计要解决的第一个问题业务这么大从哪下手一个反直觉的答案是——不是从代码下手。绝大多数重构项目死掉就死在上来就看代码、看表结构、想怎么拆这一步。DDD 的顺序正好反过来先看业务再看代码。为什么因为代码结构腐化是果业务知识混乱才是因。如果连哪些业务是命根子、哪些是辅助都没在团队里达成共识任何拆分方案都是拍脑袋。你拆得很优雅三个月后照样别扭因为根上的业务认知就没对齐过。战略设计这一上一下两篇就是教你怎么把业务版图先画出来。上篇本篇讲三件事子域三分法、事件风暴、通用语言。下篇讲限界上下文那是模型真正的户口所在地。二、子域三分法把钱花在命根子上把整个业务切成若干子域Subdomain然后按投入等级分成三类。这是战略设计最朴素、也最被低估的一步。类型定义例子电商投入策略核心域Core Domain企业赚钱的竞争力所在必须自研做精交易、推荐算法最优秀的团队、最多的资源支撑域Supporting Subdomain必不可少但不是卖点库存、物流、客服够用就好适度投入可定制开发通用域Generic Subdomain所有公司都一样没有差异化认证、短信、支付通道对接直接用开源 / 云服务 / 采购这张图把三类子域和它们的特征摆在一起一眼能分清三分法的核心价值不在分类本身而在资源配置。一个 10 人团队如果平均用力核心域反而做不出竞争力——好钢没用在刀刃上。我见过太多团队把最贵的资深工程师耗在通用域上去手写一套认证、一套短信网关而核心的交易链路反而没人精雕。这是本末倒置。那怎么判断一块业务到底归哪一类不用背定义连续问三个问题就够了我的设计笔记 · 一子域三分法里最容易被误解的是核心域。核心域没有标准答案它取决于公司战略不是取决于技术难度。同样是电商有的公司核心竞争力在供应链那库存就是它的核心域要自研做精有的公司核心竞争力在内容种草那社区才是核心域。一个做交易起家的团队和一家做履约起家的团队对同一个库存子域的归类可以完全相反。所以我特别警惕一种说法这块逻辑最复杂所以它是核心域。复杂不等于核心。复杂度是技术负担核心度是商业价值。两者一定要分开看否则你会在最不赚钱的地方投入最贵的人。还有一点要强调子域划分不是一次性的。业务方向变了子域地图要跟着重审。去年还是支撑域的营销今年公司主打私域增长它可能就得升格为核心域。三、怎么划分子域事件风暴Event Storming三分法给了判级的尺子但还没告诉你边界画在哪。划边界最实用的工具是 Alberto Brandolini 发明的事件风暴Event Storming——一种工作坊方法用领域事件做抓手让业务和技术在同一张白板上对齐。什么是领域事件领域事件是领域内已发生的、业务人员关心的事实命名一律用过去时订单已创建、库存已扣减、支付已完成、退款已发起。注意是已发生——它描述事实不是命令。这一句话就能把技术和业务拉到同一频道业务人员听得懂订单已创建也只对这种事实感兴趣。操作流程一次标准的事件风暴我按下面六步走头脑风暴全员产品、运营、开发、测试把脑子里能想到的领域事件写橙色便利贴用过去时往墙上贴按时间轴排序把便利贴按业务发生的先后顺序排成一条线去掉重复、补齐缺口按亲疏聚簇谁发起、谁关心、谁紧挨着谁关系近的贴成一簇标记关键决策用粉色便利贴标出业务规则和策略点比如等级不足则拒单识别参与者与命令黄色贴角色谁触发的蓝色贴命令触发事件的动作找边界簇与簇之间的空隙就是子域 / 限界上下文边界的候选。最妙的是第 6 步。一次工作坊同时完成了事件梳理和边界识别两件事——这恰恰是事件风暴最大的效率优势你不是在写完代码后才争论这块该归谁而是在白板上当场就把分歧解决掉。同样一块业务两种开局差别有多大一张图说清楚我自己的经验是直接写代码的团队把最贵的争论边界、归属、术语挪到了改不动的阶段——等代码都耦合在一起了再谈拆分返工成本是指数级的。而先风暴的团队逻辑边界先定物理拆分只是顺水推舟可逆、低成本。一个电商交易域的事件风暴产出的簇长这样节选关键观察交易簇和库存簇之间的那条线就是限界上下文的候选边界。这件事 03 篇会展开讲但你现在要记住一个结论——簇间空隙 边界候选这是事件风暴送给你的免费边界。四、通用语言让代码说业务的话边界画完进入具体的建模之前还有一块地基必须打——通用语言Ubiquitous Language。这是贯穿全系列的一条主线也是 DDD 里最容易被当成命名规范而轻视的一条。一个词三套说法我们团队真实发生过的事产品经理的文档写的是核销前端接口字段叫status: 2后端代码里叫updateCouponState。三个词指同一件事。每次沟通都要翻译一遍产品说核销前端说状态 2后端说更新状态。新人上手成本极高需求评审永远对不齐——因为根本没有人说同一种语言。解法建立通用语言表把术语、命名、代码体现、禁用说法统一成一张表钉在团队 Wiki 上业务术语英文命名代码体现禁用的替代说法核销优惠券redeemCoupon.redeem()updateStatus(2)、stateChange库存锁定lockStock.lock(qty)deduct、freeze订单履约fulfillOrder.fulfill()ship、deliver 混用秒杀活动flashSaleFlashSaleActivityseckill音译、rushBuy这张表的价值远不止统一叫法这么简单。一旦你要求代码命名必须能对上业务语言很多模型缺陷就藏不住了你会发现业务方嘴里的核销和使用其实是两件事而你的表里只有一个status字段——语言对不上的背后往往是模型本身就漏了概念。维护规则三条通用语言表放在团队 Wiki需求评审时同步更新——评审中出现新词当场定命名不带回技术那边再翻译代码 Review 的检查项之一命名与语言表一致不一致就是 Review 不通过术语在限界上下文内必须唯一跨上下文允许同名不同义比如商品在目录上下文和库存上下文含义不同这是允许的03 篇细讲。我的设计笔记 · 二我早年以为通用语言是锦上添花的软东西后来踩过一次大坑才改观。当时一个账户冻结 / 账户止付 / 账户挂失三个词在业务口是三种不同风控动作到了代码里全被我合并成一个account.freeze()因为我觉得反正都是不让动钱。结果上线后风控要区分客户主动挂失和系统自动止付两条不同流程我的模型根本表达不出这种差异只能到处加if (type ...)的补丁。教训语言不一致本质是概念没拆清。通用语言表不是给新人看的字典它是模型正确性的第一道闸门。命名对不上业务那天往往就是模型开始腐化的第一天。五、实战给一个中型电商画子域地图光讲方法太虚来一个真实的体量日订单 10 万团队 12 人单体应用 40 万行。我们用上面的方法把它的全域切成 7 个子域分类和资源决策一张表落定子域三分法归类资源决策交易订单 / 购物车 / 促销、推荐引擎核心域派 2 名资深工程师长期投入代码规范按最高标准慢就是快库存、物流、营销优惠券支撑域普通团队维护允许适度定制不追求极致认证授权、消息通知、支付网关对接通用域Keycloak 云消息服务 聚合支付 SDK一行不自己写你看子域划分的产出从来不是一张漂亮的图而是一张钱和人该往哪砸的清单。图只是清单的载体。六、子域不是微服务也不是包写到这必须澄清一个高频误解否则你下一步就会走偏。子域 ≠ 微服务。子域是业务的逻辑划分这是哪块业务、花多少钱做微服务是部署的物理形态怎么上线、怎么扩容。一个子域可以是一个微服务也可以是单体里的一个模块——09 篇会讲渐进式落地的三种形态核心结论先记住先逻辑后物理。顺着这个逻辑子域和限界上下文的关系也就清楚了这是本篇最该拎清的一对概念子域属于问题空间回答该不该做、花多少钱做、归谁管限界上下文属于解空间回答模型住哪、术语在哪唯一生效、边界画在哪。一个子域通常对应一个限界上下文但两者层次完全不同。事件风暴里我们先用簇把子域问题空间划出来下一步才在簇的边界上立起限界上下文解空间。子域是地图上下文是户口。下一篇我们就走进这个户口里看模型到底被圈在哪些边界内、边界与边界之间又该怎么相处六种上下文映射模式。如果子域划分错了怎么办别慌这正是先逻辑后物理的好处逻辑边界调整的成本远低于物理拆分。识别信号比如交易域反复找库存域要本该自己缓存的数据→ 回到事件风暴重新聚簇 → 调整边界。代码还没拆成微服务调整只是挪几张便利贴的事。本篇的三个自查动作我做成了一张卡贴在这里方便收藏七、本篇小结一句话收束先划子域再动代码。用外包会不会失去竞争力这一个问句区分核心域 / 支撑域 / 通用域三分法的产出是一张资源清单事件风暴用领域事件做抓手一次工作坊同时完成事件梳理与边界识别把最贵的争论消灭在白板上通用语言表是所有后续建模的地基语言不一致的本质是概念没拆清子域是问题空间的地图限界上下文是解空间的户口两者先逻辑后物理。下一篇进入限界上下文——模型真正的户口所在地以及边界与边界之间的六种相处方式。八、系列目录篇主题一句话00系列导读这条学习路线怎么走三类人怎么读01为什么需要 DDD规则副本的代价与三条原则02战略设计上本文先划子域再动代码子域三分法、事件风暴、通用语言表03战略设计下限界上下文与六种上下文映射模式04战术设计上实体、值对象、聚合的建模与三条铁律05战术设计下领域服务、领域事件、仓储与工厂06架构模式四层架构、六边形架构与依赖倒置07实战案例一电商订单系统聚合与事件驱动建模08实战案例二银行转账跨聚合的最终一致性09实战案例三40 万行单体如何按上下文渐进拆分10落地与误区六步路线图、七个高频坑、体检清单下一篇03 · 战略设计下限界上下文—— 模型真正的户口所在地以及边界与边界之间的六种相处方式。关于作者技术原点YuandianIT985 计算机硕士十年一线研发经历先后在头部互联网公司做交易与履约现于金融行业负责信贷核心、风控与账务系统的架构设计累计面试近千人带过 50 新人长期负责技术团队的技术选型与架构评审关注方向复杂业务系统建模DDD / 事件驱动 / 一致性设计与AI 工程化落地写作原则只写自己动手做过的只给能落地的结论方案必须带代价我信一句话架构的优劣不在图上在第三次需求变更时的手感上。关于技术原点始于技术归于原点—— https://yuandianit.com技术原点是一个基于Spring Boot 3 Vue 3前后端分离的自有技术平台把「内容创作 付费专栏 AI 辅助 资源交易」完整跑通——不是一个博客 Demo能力说明 文章系统Markdown 创作、分类标签、归档时间线、阅读量 / 点赞 / 收藏、关键词搜索 Wiki 知识库专栏化知识库、目录树导航、整册解锁 ——本 DDD 系列会整理成册放在这里 AI 助手接入智谱 / OpenAI / 通义千问 / DeepSeek 多模型支持 SSE 流式追问 付费阅读四级阅读门禁与付费专栏支持单篇与整册 社区商城源码与服务商品、微信 Native 扫码支付、订单与下载鉴权⚙️ 后台管理内容与用户管理、sa-token 权限、操作日志、定时任务、Knife4j 接口文档为什么要到平台上读这个系列代码和图都在线渲染架构图、代码高亮、一键复制比看截图舒服读到不懂的地方直接问 AI平台内置多模型 AI 助手可以就某一篇继续追问不必等我在评论区回成册阅读系列在平台上按 Wiki 专栏组织目录树跟随适合系统学一遍平台本身就是源码文章里讲的依赖倒置、事件驱动、支付闭环、AI 流式对话都能在平台源码里找到真实落地——理论和实现互为注解。立即访问https://yuandianit.com
阅读完成 · 觉得有帮助?