这两年跟我聊领域建模的人越来越多了。但大多数人的第一反应是问“用什么工具画图”“UML 是不是必须的”“到底该建类图还是 ER 图”,每次听到这种问题,我都有点着急——工具从来不是瓶颈,脑子里有没有一张“业务结构图”才是。领域建模这件事,卡住大多数人的不是画图技巧,而是不知道怎么从一团乱麻的业务描述里“提炼结构”。这篇“认知篇”,就想把这件事讲透:模型到底是什么、业务里的结构藏在哪儿、怎么把它们捞出来、捞出来之后怎么判断捞得对不对。适合正准备接触 DDD、或者已经在做业务分析但总觉得建模无从下手的开发者、架构师和产品经理。
1. 先忘掉 UML:模型不是业务的照片,而是业务的一幅“地图”
很多人对领域建模有一个根深蒂固的误解,觉得模型越接近真实业务越好,最好把业务里每一个细节都塞进去。这个想法恰恰是建模失败的起点。建模这件事的本质不是“复制”,而是“裁剪”;不是“拍照片”,而是“画地图”。
1.1 照片和地图的区别,就是业务描述和领域模型的区别
一张照片是什么样?镜头里有什么,照片上就有什么,树叶、电线杆、路人甲,一样不落。如果把业务原样搬进模型,你就会得到一大堆“电线杆”式的概念:员工编号、部门编号、备注字段、打印模板、操作日志……它们每一个在业务里都有出处,但放到模型里只会让核心结构被淹没。
地图是什么样?地图是有选择的简化。一张城市地铁图,不会把每个小区都画上去,它只保留跟“坐地铁”这件事有关的信息——站点、线路、换乘点。它甚至故意“扭曲”了真实的地理距离,因为对乘客来说,站与站之间的相对顺序比绝对距离更重要。
领域模型就是这张地铁图。它的服务对象不是“完整记录业务”,而是“让业务的核心规则和关系变得可理解、可讨论、可演进”。所以,建模的第一步不是收集更多细节,而是想清楚一个问题:这张图是给谁看的、用来做决定的? 这个目的定了,哪些东西该保留、哪些东西该舍弃,自然就有答案了。
1.2 领域模型的三层结构:概念、关系、规则
很多人以为模型就是“画几个方框,连几条线”。其实一张模型图里通常藏着三层信息,少了任何一层,模型都是不完整的。
- 概念层:业务里反复出现、绕不开的“名词”。比如“会议室”“预订”“审批”“员工”。这一层回答的是“业务里有哪些核心事物”。
- 关系层:概念之间的联系方式。比如“员工发起预订”“审批针对预订”“会议室被预订占用”。这一层回答的是“这些事物之间怎么互相作用”。
- 规则层:约束概念和关系的“必须”与“不能”。比如“只有经理级别以上才能预订大会议室”“同一个时间段会议室不能被重复预订”。这一层回答的是“业务允许什么、禁止什么”。
我见过太多人建模型,只画了概念和关系,忘了规则。结果模型图看起来干干净净,一旦落到代码里,规则全散落在 if-else 里,模型形同虚设。记住:规则是模型的灵魂,没有规则的模型只是名词堆砌。这也是为什么后面讲“提炼结构”时,我会反复强调去业务描述里找“必须”“不能”“如果……那么……”这类的句子。
1.3 模型是为“沟通”服务的,不是为“数据库”服务的
另一个常见误区,是把领域建模直接等同于数据库设计。有人跟我说“我们项目里已经有 ER 图了,还需要领域模型吗?”这个问题本身就是没搞清楚二者的服务对象。
ER 图的服务对象是“存储”。它关心的是字段怎么落表、主外键怎么关联、索引怎么建,它的主语是数据。领域模型的服务对象是“业务理解和业务规则表达”。它关心的是“谁在什么条件下可以对什么做什么”,它的主语是行为和规则。一个面向存储,一个面向业务沟通,服务对象完全不同。
举一个最简单的例子:在数据库里,“预订”和“审批”是两张表,通过外键关联。但在领域模型里,“审批”不是一张独立的数据表,而是“预订”这个业务对象在某个状态下经历的一个事件。如果你建模的时候脑子里装的全是表和外键,你就天然会错过这种“状态流转”的视角,而状态流转恰恰是业务规则最密集的地方。所以做领域建模之前,请先把数据库设计那套思维暂时放一放。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 业务里的结构藏在哪儿:语言、规则与行为的三条线索
明确“模型是地图”之后,下一个问题就是:地图上的“地标”从哪来?也就是,业务的“结构”到底藏在哪里。根据我做过的这么多项目,结构基本藏在这三个地方:业务语言里反复出现的词、业务规则里的条件和例外、业务行为发生的时间顺序。
2.1 业务语言是结构的第一现场
有个概念在领域驱动设计里叫“通用语言”(Ubiquitous Language),听起来很高深,说白了就是:业务人员在讨论业务时,反复使用、绕不开的那批词。这些词就是模型概念的候选对象。
你只需要做一件事:去旁听业务会议,或者把需求文档从头到尾读两遍,把名词全部圈出来,数一数谁出现频率最高。出现频率高的名词,往往就是业务的核心概念。比如在会议室预订系统里,你可能圈出“会议室”“预订”“员工”“审批”“时间”“取消”“释放”这些词。而“公司”“楼层”“茶水间”这些虽然也出现,但频率明显低,也没有直接绑着业务规则,它们就是可以暂时放生的“电线杆”。
但这里有个陷阱:业务人员口中的同一个词,在不同场景下可能指完全不同的东西。比如“审批”,有时候指“审批这个动作”,有时候指“审批结果”,有时候指“一张审批单”。如果你不注意区分,建模的时候就会把一个含义混杂的词当成一个单一概念,后面所有规则都会跟着乱。所以,圈出高频名词之后,还要做一步:给同义词和近义词“合并同类项”,给多义词“分家”。这一步做得好,模型就成功了一半。
2.2 业务规则里的条件与例外,是结构密度最高的地方
如果说名词是模型的骨架,规则就是模型的血肉。业务里最值钱的信息,几乎都藏在那些带“必须”“不能”“只有……才”“如果……就”的句子里。这些句子直接定义了业务边界和约束,你不把它们挖出来,模型就是空壳。
举个例子,同样是会议室预订,“员工可以预订会议室”这条规则就很弱,模型里仅仅体现一个关联关系。但加上“大会议室必须由部门经理审批,小会议室由部门主管审批”之后,“会议室”这个概念就被分出了“大小”两种类型,“审批”这个概念也被分出了“经理审批”“主管审批”两条路径,整个模型的复杂度立刻上来了。
规则的另一个特点是:规则的例外往往比规则本身更能暴露结构。比如“员工提前不到一小时取消预订,必须填写取消原因”这条规则,它其实在暗示“取消”并非一个无差别动作,而是有“正常取消”和“临期取消”两种变体。再比如“如果员工超过预订时间十五分钟未到场,系统自动释放会议室”,这条规则实际上在暗示“预订”有一个“超时未到”的状态,且存在“自动释放”这个机制。这些细节,都是模型里状态和规则的直接来源。所以读需求文档时,别急着划线,先把所有“如果”“但是”“除非”圈出来,一条条问:这条规则约束的是谁?它在什么条件下成立?它产生了什么新的状态或变体?
2.3 行为的时间顺序,暴露了对象的状态流转
业务的第三处结构,藏在“事情发生的先后顺序”里。把业务里所有关键事件按时间排一排,你会发现很多被忽略的状态。比如会议室预订的完整生命周期大概是:发起预订 → 待审批 → 审批通过(或拒绝)→ 到点使用 → 释放。但加上规则之后,这个生命周期会变得丰满:发起预订后如果超过一天没人审批,要自动提醒;审批通过后如果超时未到,要自动释放;预订使用前一个小时取消要填原因。
这一串事件排下来,你实际上得到了一张状态图。而每个方框和每条箭头,都对应模型里的一个状态和一条规则。这就是为什么我一直建议:建模时不要只盯着“名词”,一定要追问“这个东西从生到死会经历哪些状态”。思考状态流转,是发现规则、验证模型完整性的最有效方法之一。
3. 提炼结构的四条路径:名词、动词、规则与事件怎么配合用
知道了结构藏在哪儿,接下来就是具体操作了:怎么把它们一条条捞出来。我把自己经常用的方法归纳成四条路径,实际项目里通常要组合使用,才不容易漏。
3.1 第一条路径:名词圈定法
这是最直观、也最容易上手的方法。把需求文档里的名词全部抓出来,然后做两件事:合并同义项、剔除弱业务概念。
名词圈定法有个容易犯的错误,就是把“所有名词都当领域概念”。打个比方,需求里出现“会议室编号”,编号不是概念,会议室才是概念;出现“预订人姓名”,姓名不是概念,预订人(员工)才是概念。判断标准很简单:这个概念有没有自己的状态?有没有绑定的规则?如果它只是另一个概念的属性,就不要单独建模。
我常用的做法是画一个两列表格,左边放“候选名词”,右边放“它在模型里是概念还是属性”。比如:
| 候选名词 | 判断 | 理由 |
|---|---|---|
| 会议室 | 独立概念 | 有状态(空闲/使用中/维护中),有规则(不同类型有不同审批权限) |
| 会议室面积 | 属性 | 不单独变化,不携带规则,只是描述会议室的一个数据 |
| 预订 | 独立概念 | 有完整生命周期,被多条规则约束 |
| 预订人 | 独立概念 | 有审批权限规则,绑定员工层级 |
| 取消原因 | 属性 | 不单独存在,只是取消这个行为产生的一个信息 |
这个表一画完,哪些概念要进模型,基本就浮出水面了。
3.2 第二条路径:动词驱动法
名词圈出来之后,还有一层要做:看这些名词之间到底怎么“动”。动词是“谁在操作谁”的信号。比如“员工发起预订”“经理审批预订”“会议室被占用”“系统释放会议室”。把动词找出来,你会发现其中暗含“依赖方向”和“聚合边界”。
这里有一个核心原则:方向跟着职责走,谁对一件事负全责,谁就是聚合根。比如“预订”这个行为,表面上是“员工发起”,但一旦预订被发起,后续的审批、取消、释放、超时处理全都围绕“预订”这一个对象转。所以“预订”是一个很好的聚合根,它把所有相关规则收拢在自己周围,而“员工”和“会议室”更像是它“引用”的其他对象。
为什么要这么分?因为建模的最终目的是让业务规则有一个清晰的“归属地”。如果规则散落在各个名词之间、互相跨对象引用,代码写起来就会变成到处传参、到处 if-else。动词驱动法,就是在帮你找到“规则的归属地”。
3.3 第三条路径:规则提取法
这个方法直接面向规则层。把业务文档里所有带约束意味的句子摘出来,然后对每一条问三个问题:
- 这条规则约束的对象是谁?(确定规则的宿主)
- 它在什么条件下触发?(确定规则的前置条件)
- 它导致了什么结果?(确定规则产生的状态变化或动作)
举个例子。原文说:“大会议室必须由部门经理审批,小会议室由部门主管审批。”摘出来之后分析:规则约束对象是“审批”;前置条件是“预订的会议室类型为大/小”;结果是“审批人类型不同”。这条规则直接决定了“会议室”要有“类型”属性,也决定了“审批”有不同的路径。再比如:“超过预订时间十五分钟未到,系统自动释放会议室。”约束对象是“预订”;前置条件是“超时未到”;结果是“预订状态变为已释放”。这条规则直接给“预订”增加了一个“使用中”和“已释放”的状态。
规则提取法是四者中产出最密集的。实际做的时候,建议把每条规则编号,比如 R1、R2、R3,然后把规则和它对应的概念、事件关联起来。这样最后生成的模型,每一个设计决定都能溯源到某一条业务规则上,跟业务方对齐的时候也更有底气。
3.4 第四条路径:事件回放法
最后一条路径适合用来做“完整性校验”。把业务从头到尾捋一遍,把所有“发生的事”按时间顺序列出来,然后检查一个问题:每个事件发生之前和之后,系统的状态分别是什么?
举个例子:
| 时间线 | 事件 | 状态变化 |
|---|---|---|
| T1 | 员工发起预订 | 无 → 待审批 |
| T2 | 经理审批通过 | 待审批 → 已批准 |
| T3 | 预订开始,员工到场 | 已批准 → 使用中 |
| T4 | 预订结束,员工离开 | 使用中 → 已释放 |
| T5 | 员工提前一小时取消 | 待审批/已批准 → 已取消 |
| T6 | 超时十五分钟未到 | 使用中/已批准 → 自动释放 |
这张表列完,你会有两个发现:一是有些时间点上状态是“空白”的,说明业务规则有漏洞;二是某些状态之间的转换是“跳跃”的,说明可能漏了中间环节。事件回放法是检验模型完整性的利器,它不直接“创造”结构,但能帮你发现结构里的洞。
四条路径的分工大致可以概括为:名词圈定法找概念,动词驱动法找关系,规则提取法找约束,事件回放法找状态。组合使用,基本能把一个业务的骨架摸得八九不离十。
4. 分辨结构的“轻”与“重”:不是所有候选概念都值得进模型
提炼结构的过程中,最考验功力的不是“找到”概念,而是“舍弃”概念。很多初学者建模失败,不是漏了什么,而是塞了太多不该进模型的东西。模型臃肿,核心结构反而看不清。
4.1 三个判断标准:状态、规则、语言地位
一个候选概念到底要不要进模型,我一般用三个问题来检验:
第一,它有没有独立的状态? 一个概念如果能经历多个状态(比如预订从待审批到已批准到已取消),说明它在业务中是“活”的,值得建模。反过来,如果它只是一个静态描述(比如会议室面积、楼层号),那它就是属性,老老实实挂在别的概念下面。
第二,它身上有没有绑定的规则? 规则是模型的灵魂,也是概念存在的最大理由。如果一个概念不携带任何规则,说明它在业务里不引发任何约束,大概率是个装饰性概念。只有概念身上挂着“必须”“不能”“如果”这些规则时,它才值得被正式建模。
第三,业务人员在讨论中是不是绕不开它? 去业务会议现场听一听,如果业务人员讨论业务时,这个名词反复出现,不用它就没法说清楚业务,那它就是一个核心概念。如果只是偶尔提一下、换个词也不影响理解,那它就很可能是边缘概念。
三个标准都满足,必进模型;只满足一两个,谨慎考虑;一个都不满足,果断舍弃。
4.2 慎重建模的“边界概念”和“历史遗留概念”
实际业务里,最让人纠结的是两类概念。一类是“边界概念”,比如“审批流配置”“权限组”这类支撑性功能里的概念。它们确实是系统的一部分,但它们不是业务的核心,而是技术方案或管理支撑衍生出来的对象。这类概念在模型中应该靠边站,甚至可以刻意弱化——否则模型会被“系统功能”带偏,而不是被“业务规则”带着走。
另一类是“历史遗留概念”。业务跑了很多年,会积累一些“以前因为某种原因引入、但现在已失去业务含义”的概念。比如老系统里有个“结算员”角色,早期是因为人工对账需要专人操作,后来系统自动化之后,“结算员”谁都可以选,但它还在下拉框里。这类概念一旦进入领域模型,会让规则无端复杂化。建模时建议胆子大一点,跟业务方确认清楚:如果这个角色已经没有专属规则,就从模型里拿掉。
4.3 “核心域”与“支撑域”:把力气花在刀刃上
领域建模有一个重要但常被忽视的指导思想:不是所有业务都值得投入同样的建模精力。一个系统里,真正决定业务价值、最需要严谨建模的,往往只有一个核心区域。其他区域,要么是辅助支撑,要么是通用能力,不需要用“领域模型”的精细度去对待。
判断哪个是核心域,有一个很朴素的方法:问自己,这个系统如果明天被竞争对手抄走,对方最想抄走的是哪块? 那块逻辑就是核心域。比如会议室预订系统,核心域可能是“预订与审批规则调度”,而“员工通讯录”“通知消息”“操作日志”都是支撑域。建模的时候,核心域的模型要精雕细琢,支撑域做到够用就好,别把精力平均分配。
5. 一个完整实例:从三段混乱需求到一套可讨论的领域模型
讲了一堆方法论,不如直接看一个完整实操案例。下面我带你走一遍:从一段混乱的原始需求,到一套可以拿给业务方讨论的模型结构。这个过程就是“提炼”二字最直观的体现。
5.1 原始需求描述
假设你拿到这样一段描述(这种描述格式,我相信所有做过业务系统的人都不陌生):
员工要订会议室,在系统里选时间,然后要领导审批,通过了就能用。会议室分大小的,大会议室要部门经理批,小会议室部门主管批就行。如果审批没通过要通知员工。预订了不来,超过十五分钟系统就自动取消,把会议室腾出来。用完了要释放。临时取消可以,但提前不到一小时取消的,要填一下取消原因。同一个时间段,一个会议室不能同时被两个预订占着。
这段话信息量不均匀、逻辑有交叉、有些规则藏在字缝里。直接拿这段话去做系统,开发肯定会一脸懵。现在按前面的方法走一遍。
5.2 提炼过程拆解
第一步,名词圈定。反复出现的名词有:员工、会议室、预订、时间、审批、系统、取消、释放、原因。逐一过三关:“会议室”有状态(空闲、使用中、被预订),有规则(大小决定审批路径),是业务核心语言——进模型;“员工”有状态(在职/离职),但没有直接绑业务规则,是预订的发起者——进模型,但层级较低;“系统”不是业务概念,是技术执行者的代称——不进模型;“取消原因”没有独立状态、没有规则,是取消事件携带的信息——作为属性。
第二步,规则提取。把带“必须”“不能”“如果”的句子全摘出来:
- R1:预订会议室需要审批通过才能使用。
- R2:大会议室必须由部门经理审批。
- R3:小会议室必须由部门主管审批。
- R4:审批不通过要通知员工。
- R5:预订开始后超过十五分钟未使用,自动取消(释放会议室)。
- R6:提前不到一小时取消,必须填写取消原因。
- R7:同一个会议室,同一时间段不能被重复预订。
每条规则都能找到宿主对象。R1、R5、R6、R7 的宿主都是“预订”,说明“预订”身上背着最多的规则——它是聚合根的强候选。R2、R3 的宿主是“审批”,同时它们受“会议室类型”影响。这暗示“会议室”需要一个“类型/规格”属性。
第三步,事件回放。把“预订”的生命周期拉一遍:发起 → 待审批 → 审批通过 → 使用中 → 释放;待审批/已批准 → 取消;已批准 → 超时未到 → 自动释放。注意,这段需求里有一个隐含状态:审批被拒绝后会生成“已拒绝”状态,而且要触发“通知员工”。所以状态图应该补上。
5.3 最终的模型结构
经过上面的提炼,这个业务的模型结构大致是:
- 员工:发起预订的人。属性包括姓名、部门、职位级别。
- 会议室:可被预订的资源。属性包括名称、类型(大/小)、可容纳人数。
- 预订:聚合根。属性包括预订时间区间、状态(待审批/已批准/已拒绝/使用中/已取消/已释放/超时取消)、取消原因(可空)。包含行为:发起预订、提交审批、取消预订、确认到场、完成释放。
- 审批:预订状态流转的触发点。属性包括审批人、审批结果、审批意见。大小会议室对应不同的审批规则。
注意,原始需求里的“系统自动取消”“系统自动释放”,在模型里并不需要一个叫“系统”的概念。它只是预订对象在特定时间条件满足时执行的一个行为而已。
5.4 这个模型和原始需求对比,解决了什么问题
跟原始那段话相比,这个模型做了什么?第一,概念边界清晰了。“预订”和“审批”谁是谁的父级,一眼能看出来;第二,规则归属明确了。每条规则都能找到它依附的对象,没有人再需要去 if-else 里翻;第三,状态流转完整了。从生到死,预订经历哪些阶段,一目了然;第四,它可以直接拿给业务方讨论。“你们公司是不是所有大会议室都由经理审批?如果经理不在呢?”——这类问题一旦抛出,业务规则的漏洞会被快速暴露并补全。
这个案例看着简单,但它的价值在于完整展示了“从业务中提炼结构”的思考路径:不是把业务描述翻译成代码,而是对业务描述进行重组和抽象,让核心结构显现出来。
6. 模型立没立得住:三个验证问题和一个持续演进的提醒
模型做出来,如何判断它好不好?这里说的“好不好”,不是画得漂不漂亮,而是在真实项目和真实沟通中能不能站得住。
6.1 给业务专家讲一遍,看不看他的反应
模型搭好之后,找个业务专家,不用讲技术术语,就拿着名词清单和状态流转给他讲一遍:“你看,这个系统里的核心是预订,它从发起到释放,会经历这几个阶段,每个阶段有这些规则约束。是不是这么回事?”如果业务专家点头,说“对,就是这么个流程”,说明模型抓住了业务结构。如果他频繁说“不是,我们这儿还有……”或者“不对,我们其实是……”,不要急着辩解,那说明模型漏了东西,或者概念抽象错了。
这一步特别能检验“通用语言”是否建立。如果你跟业务专家讲“预订状态机”,他听不懂,但你换成“一张预订单,从申请到使用完,中间会经历哪些状态”,他发现你理解得比他还透,那你就真的提炼对了。
6.2 拿新需求试探模型的“稳定性”
模型好不好,还有一个更硬核的验证方法:拿一个新需求去测试它,看模型的改动面有多大。设计模型的时候,预期是“新需求到来时,模型的主体结构保持不变,只需要增加新状态、新规则或新概念”。如果每来一个新需求,你都要推翻重来,说明模型建立得不正确——你没有找到业务真正的稳定核心。
举个例子,上面那个会议室预订模型,如果新需求来了:“管理层会议室需要额外经过行政审核。”这个需求改动量应该很小:只需要给“审批”增加一条规则分支,或者给“预订”增加一个状态“待行政审核”,主体结构完全不动。但如果模型需要大改,那就要反思:当初把某个规则挂在哪个对象上,是不是挂错了?核心和支撑是不是被颠倒了?
6.3 看团队讨论时用的是谁的词汇
最后一个验证方法,也是我在项目里比较看重的软性指标:团队讨论需求时,是用业务原词在沟通,还是用模型里的词在沟通。如果模型真的提炼出了业务的结构,你会发现,开发、产品、业务三方开会时,大家嘴里说的自然就变成了“预订状态流转”“审批规则”“释放条件”这些统一的词。而不是开发说“那张表”、产品说“那个流程”、业务说“我们以前是这么干的”这种各说各话。
反过来,如果模型建完,团队讨论时完全用不上、还是各说各的,那这个模型大概率只是纸面模型,没有进入实际业务认知。
6.4 模型不是一次定稿的雕塑,而是会持续修改的地图
最后还要泼一盆冷水:模型不是静态的。业务会变,规则会调,概念会重构。领域建模的价值,不是给你一张永不修改的图纸,而是让你随时知道“业务结构变了,我该在哪个位置做调整”。所以不要太追求“一次到位”,也不要因为模型被修改就觉得自己之前建错了。建模是一个随着业务理解加深而不断迭代的过程。每一次修改,都是一次对业务结构的重新提炼。
写在最后的一点心得
带团队建模这些年,我最大的感触是:绝大多数人不是不会建,而是舍不得“减”。一看到业务描述里有这个概念那个名词,就想着“先都放进去再说”,结果模型出来像一本流水账,表面上覆盖了所有业务,实际上一张图什么都解释不了。建模最难的其实不是技术功力,而是克制。你要时刻问自己:这个模型是让业务变清楚了,还是变复杂了?是让讨论变顺畅了,还是变费劲了?想不清楚就往这个方向想:把业务当作一块玉,建模不是在玉上多刻几刀,而是把包在外面的石皮剥掉,让玉的纹理自己露出来。至于用什么工具画图,说实话,一张白纸加一支笔就够了。结构在脑子里,不在软件里。希望这篇“认知篇”能帮你把那层石皮认出来。下一篇实操篇,再跟你们聊聊怎么把模型一步步落成代码。
