业务建模真正难的不是画模型,而是定义问题
我重新读极客时间《如何落地业务建模》时,最有用的不是某个建模技巧,而是一个更朴素的判断:业务建模首先是定义问题的方法,其次才是设计解决方案的方法。
很多架构争论卡住,不是因为大家不懂技术,而是因为问题一开始就没定义清楚。要不要 DDD?要不要微服务?要不要中台?要不要 SaaS 化?这些问题一旦脱离业务目标,很快就会变成站队。每个人都能讲一套方法论,但没人能说清楚:我们到底在解决哪个业务问题,为什么这个问题必须用这种结构解决。
这门课的价值在这里。它没有把 DDD、事件建模、四色建模、8X Flow、微服务、中台和 SaaS 化讲成一串孤立工具,而是把它们放在同一条线里:怎么从业务里找到结构,再把结构映射到软件实现。
先定义问题,再谈模式
业务建模最容易被做成需求翻译。业务方讲流程,产品写需求,研发把名词抄进类名和表名。这样当然也能交付系统,但模型只是文档里的装饰,不会真正影响代码。
更麻烦的是另一种情况:研发先拿解决方案反推问题。看到复杂流程,就想状态机;看到多个系统,就想微服务;看到复用诉求,就想中台;看到“领域”两个字,就开始建实体、值对象、聚合和仓储。
这不是业务建模,是套模板。
真正的业务建模要先回答两个问题:
- 业务上,什么才是正确的问题定义?
- 技术上,什么结构能支撑这个定义长期演化?
这两个问题必须一起看。一个在单体里合理的聚合,到了云平台上可能因为弹性诉求不同而需要拆开;一个在同步流程里看起来简单的业务动作,进入异步服务生态后就会暴露出等待、超时、补偿和违约。架构不是建模完成后的实现细节,它会反过来影响模型的形状。
DDD 的核心不是写出一堆领域对象
DDD 很容易被误解成编码风格。实体、值对象、聚合、仓储、领域服务,这些东西一出现,团队就以为自己在做 DDD。
但 DDD 的核心不是目录结构,也不是“所有逻辑都塞进实体”。这门课把 DDD 压缩成一句话:两关联一循环。
| 元素 | 含义 | 真正检查点 |
|---|---|---|
| 模型与实现关联 | 模型结构能映射到代码结构 | 模型改了,代码是否也能定位到对应变化 |
| 统一语言与模型关联 | 业务讨论使用模型里的概念 | 需求讨论是否会反向暴露模型问题 |
| 知识提炼循环 | 讨论、发现问题、精炼模型、验证语言 | 模型是否在反馈中变好 |
这解释了为什么“模型与软件实现关联”这么关键。如果模型只是分析阶段的图,代码按另一套结构实现,模型和实现就分裂了。业务方讨论一套语言,研发维护另一套结构,所谓统一语言根本跑不起来。
极客时间订阅的例子很典型。贫血模型会把用户、订阅、订阅价格等逻辑拆散到 DAO、Service 或脚本里。代码看似简单,但“用户订阅的专栏”这个业务概念没有在模型中成为一个整体。富含知识的模型则会把订阅放回用户相关的业务结构里,让“用户拥有订阅、订阅总价属于这个整体”在代码中能被看见。
关键不在于实体里一定要写多少方法,而在于概念、行为和实现不能脱节。只要模型和实现断开,DDD 就只剩术语。
统一语言不是术语表
很多团队做统一语言,最后会得到一份词汇表。词汇表有用,但它不是 DDD 里的统一语言。
统一语言必须基于领域模型。业务方用模型里的概念表达需求,技术方通过模型和代码反馈业务概念是否成立。模型变了,语言也要变;代码重构了,业务概念也可能被迫重新命名。
比如“用户可以订阅多个专栏”不是一句普通需求。如果模型里有 User、Subscription,以及它们之间的关系,这句话同时指向业务规则和实现结构。
后来如果出现“企业员工可免费阅读专栏”,就不能只想着加字段。它可能不是普通订阅,而是另一套合同关系:企业购买访问权,员工只是权益使用者。这个判断会改变模型,也会改变语言。继续把它叫“订阅”,代码迟早会被各种特殊分支污染。
统一语言真正有价值的地方,是让技术方有权参与业务定义,也让业务方能影响模型和实现。研发不能躲在“我只是实现需求”后面,业务方也不能只把流程扔给研发翻译。
传统对象模型会碰到三个现实障碍
DDD 的对象模型在真实系统里会遇到不少阻力。这些阻力不是 DDD 错了,而是对象模型必须面对性能、上下文和依赖。
第一个障碍是性能。对象聚合和数据库查询经常不匹配。用户拥有大量订阅,如果直接在 User 里加载所有 Subscription,会遇到 N+1 或一次性加载过多数据的问题;如果把查询和统计都丢给 SubscriptionRepository,聚合逻辑又会泄漏出去。
一个更稳的办法,是把“关联关系”本身建模成对象,比如 MySubscriptions。它既表达业务上的“我的订阅”,也封装分页、统计、计数这些实现细节。这里的重点不是发明一个类名,而是把技术约束翻译成业务能理解的概念。
第二个障碍是上下文过载。同一个用户,在购买上下文里是买家,在内容上下文里是读者,在运营上下文里可能是推广者。如果所有行为都塞进 User,这个对象会越来越大,也越来越没人敢改。
角色对象和上下文对象解决的是这个问题:同一个实体在不同场景里扮演不同角色,行为要放回对应语境,而不是堆进一个万能对象。
第三个障碍是分层依赖。传统分层经常把基础设施放在领域层下面,但真实业务逻辑又需要支付、邮件、网银、短信这些能力。课程里提出的“能力供应商”很有意思:不要把基础设施只看成技术接口,而是把它拟人化为业务能力提供者。网银转账可以是“出纳”,邮件通知可以是“客服”。
这不是文字游戏。它逼着你说清楚领域逻辑依赖的到底是什么业务能力,而不是随便抽一个技术接口。
从对象到事件,再到凭证
如果模型要成为统一语言,它就不能只对研发友好。类图对研发有用,但业务方很难直接从类图里看到业务过程。所以课程里依次讲了角色-目标-实体法、事件建模和四色建模。
角色-目标-实体法从参与者出发:谁在系统里扮演角色,他们要达成什么目标,目标里涉及哪些实体。它适合共创,因为业务方能参与进来。但它对复杂业务流程的分析力不够强。
事件建模把入口换成“发生了什么变化”。事件是行为留下的印记。先找事件,再倒推命令、行动者、策略、聚合和读模型。事件风暴比直接画对象更容易建立统一语言,因为业务方通常更习惯描述“发生了什么”,而不是描述“应该有哪些类”。
四色建模再往前走一步。它不是靠头脑风暴找事件,而是从企业运营里的现金收入、现金支出、KPI 对比出发,沿着凭证追溯业务活动。
这里有个很硬的判断:业务活动需要留下凭证。收钱意味着承担义务,要有履约证据;付钱意味着拥有权利,要检查对方是否履约;没有现金往来的管理活动,也会通过目标和实际结果对比形成约束。
对象、事件、凭证的区别在这里:
| 方法 | 入口 | 适合解决的问题 |
|---|---|---|
| 对象建模 | 业务概念和行为 | 让代码表达领域知识 |
| 事件建模 | 业务过程中发生的变化 | 找流程、命令、角色和读模型 |
| 四色建模 | 凭证、现金流、KPI | 找业务活动背后的权责和证据链 |
这也是 8X Flow 能接上的地方。业务不是一堆对象在互相调用,业务本来就围绕权利、义务、请求、确认和凭证运转。
RESTful API 不只是接口风格
当模型稳定到一定程度,下一步不是急着拆服务,而是先看模型怎么对外暴露。
RESTful API 在这里的价值不是“URL 写得好看”,而是把模型暴露成消费者能理解的业务能力。资源设计应该从模型出发,而不是从数据库表或后端函数出发。
/users/{uid}/subscriptions 不只是一个 URL,它表达的是用户和订阅之间的模型关系。内部到底是单体查询、服务编排、惰性计算,还是异步任务,都可以藏在资源背后。消费者依赖的是业务关系,不应该依赖内部实现。
这也是 URI 稳定性重要的原因。稳定的不是字符串,而是它背后的业务关系。只要业务关系还成立,内部实现就有调整空间。
云时代把“弹性”推到了建模前台
前云时代,建模的重点是如何在单体或多层架构里维护模型与实现的一致。云时代的新约束是弹性。
弹性不是“机器多一点”。云平台真正擅长的是水平扩展:复制实例来提升吞吐,流量低时再缩回去。系统能不能用好云平台,本质上取决于能不能按不同容量诉求拆出弹性边界。
这会改变微服务的判断。
微服务不是越小越好,也不是只按业务上下文拆分。更准确地说,微服务是“以业务上下文作为弹性边界候选的云原生架构模式”。真正要问的是:把这个上下文放进独立弹性边界,是否能更好地控制成本和风险?
如果两个上下文流量和变更节奏一直一致,拆开可能只会增加协作和运维成本。如果两个上下文弹性诉求明显不同,拆开才有意义。电商里的商品浏览和支付就是典型例子,大促时两者峰值、容量诉求和失败处理方式都不同,分开扩容更合理。
弹性优先不是架构信仰,是成本判断。
业务天然偏异步,同步只是软件里的简化
拆出弹性边界后,还会遇到另一个问题:边界之间会传递压力。上游流量暴涨,下游也被带着承压,这叫弹性依赖。
云平台擅长处理依赖吞吐量的弹性依赖,却不擅长处理依赖响应时间的弹性耦合。水平扩展通常能提升单位时间处理请求的数量,但不一定能缩短单个请求的响应时间。
同步调用会把下游响应时间纳入上游响应时间。订单服务同步等支付服务,支付慢,订单也慢;支付扩容跟不上,订单侧资源也会被拖住。异步调用把“等你返回”改成“我发出请求,你在规定时间内处理完并给我结果”。关注点从响应时间转成吞吐量,云平台就更容易发挥作用。
这也解释了课程里那句很关键的话:业务天生是异步的,同步是简化。
现实世界里的权利主张和义务履约很少瞬间完成。买家下单,平台请求支付,卖家发货,承运方配送,买家确认收货,每一步都有请求、确认、等待、失败和补救。软件把这些步骤写成同步流程,是为了实现简单;到了云时代,这种简化会反过来制造弹性耦合和一致性问题。
领域逻辑和业务逻辑不是一回事
进入 8X Flow 之前,课程先做了一个重要区分:领域逻辑和业务逻辑不是一回事。
领域逻辑是与运营无关的问题域逻辑。内容系统里的专栏、文章、评论;搜索引擎里的分词、索引、爬虫;推荐系统里的特征、相似度和排序,都更接近领域逻辑。它关注问题本身。
业务逻辑是与运营相关的逻辑。它关注怎么赚钱或省钱,复杂度来自定价、分成、返现、合同、履约、绩效、成本控制这些东西。
极客时间的例子很清楚。发布文章、阅读内容、评论互动,更像内容管理系统;定价、订阅、返现、作者分成、企业版收费,则是业务运营系统。同样的订阅分成模式,换成网剧或其他内容产品也可能成立;同样的内容管理能力,放到不同商业模式下也能复用。
这个区分会影响建模方法。领域逻辑未必适合对象模型,算法模型、特征模型、决策树有时更合适。业务逻辑则很适合从合同、权责和凭证入手,因为企业活动最终都要落到合同、履约、财务和审计上。
8X Flow 的入口是合同履约
8X Flow 的基本判断是:在业务逻辑中,权责履约是最小的业务交互,合同是最小的业务上下文。
合同不一定是纸质合同。网上购物时,订单就是采购合同:商家有发货义务和收款权利,顾客有付款义务和收货权利。未付款订单关闭、预订违约扣款、延迟发货补偿,都不是技术异常,而是合同上下文里的权责项。
用 8X Flow 看业务,大致按这条路走:
- 找合同上下文,明确合同参与方。
- 找主要履约项,识别权利方、义务方、履约请求和履约确认。
- 为履约请求和履约确认寻找凭证。
- 寻找违约情况,把违约责任继续建模为新的履约项。
- 继续追溯,直到进入法律裁定等系统外边界。
- 把参与方和标的物划入领域边界或其他合同上下文。
以极客时间订阅为例,读者和极客时间之间存在专栏订阅合同。主要履约项至少包括两类:读者支付订阅费用,极客时间提供付费内容访问。支付有请求、有确认、有凭证;内容访问也可以被看成权利和义务的履约。
如果读者没有在规定时间内支付,合同可以自动作废。如果专栏断更或下架,可能触发退款、补偿或重新上架后免费阅读。这些都不应该被简单塞进“异常分支”,它们是业务规则本身。
8X Flow 真正厉害的地方,是把异步、中间态和补偿从技术问题还原成业务问题。履约请求到履约确认之间天然存在等待期;未确认、确认失败、超时,都有业务含义。
凭证角色化会暴露变化点
8X Flow 不只是能画出合同,还能帮助发现变化点。
继续看订阅支付。如果把支付确认直接建模在订阅合同内,这更像线下现金交易:读者和极客时间面对面收款开票。但真实数字化交易会引入微信、支付宝、预付费账户、企业支付等第三方或其他合同上下文。
如果订阅合同直接依赖每一种支付合同,核心业务逻辑就会被支撑逻辑拖着走。每新增一种支付方式,订阅合同都要感知它。
更好的做法,是把“支付确认”角色化。订阅合同只要求某种凭证能扮演支付确认,具体凭证可以来自移动支付协议、预付费合同、企业账户合同等不同上下文。这样,支付确认就成了一个明确变化点。
这件事不只是解耦代码。它说明业务变化点本来就藏在业务结构里。沿着合同、履约和凭证追溯,你会看到哪些履约确认可以由多种凭证扮演,哪些角色可以由不同领域系统提供,哪些地方天然适合扩展。
合同不一定是服务,履约才可能是弹性边界
8X Flow 和微服务的关系,不能简单理解成“一合同一服务”。
合同上下文表达业务一致性。一个合同里的履约项和违约项共同定义业务规则,它们构成业务上的聚合。
履约上下文更接近弹性边界。不同履约项可能有完全不同的容量诉求。订阅合同里,“访问付费内容”的流量通常远大于“支付确认”和“断更补偿”。如果为了弹性成本,把访问履约独立出来是合理的;如果所有履约项弹性一致,就没必要硬拆。
领域上下文也可能成为弹性边界。内容管理、搜索、推荐、支付能力这些领域系统,可能因为流量、算法、数据一致性和团队生命周期不同而独立部署。
所以从模型到微服务,顺序应该是:
- 先找合同上下文、履约上下文和领域上下文。
- 把它们映射成 RESTful API,先形成稳定的服务模型。
- 再根据弹性收益、业务能力和产品生命周期决定是否拆进程。
服务边界不是画图时的漂亮分割线,而是长期维护成本。没有独立生命周期、独立扩缩容收益和清晰消费者承诺的拆分,最后很容易变成分布式单体。
中台复用的不是 CRUD,而是业务模式
中台这个词之所以混乱,很大一部分原因是“前台”常被误解成前端系统。课程里更准确的定义是:前台是小而灵活、具有自主性的业务团队;中台是支撑多个小前台团队的软件平台。
中台要解决的是效能和创新之间的矛盾。平台能力越强,前台复用成本越低,效能下限越高;平台框得越死,前台自主度越低,创新上限越低。
好的中台不是把所有流程统一掉,而是在特定场景中提取可复用的业务模式,同时保留扩展点。
课程把这种可复用业务模式叫宏流程。宏流程不是具体流程,也不是空泛抽象。比如出行场景里,出租车、专车、快车、顺风车、共享单车都可以被看成一类业务:需求方提出出行需求,平台匹配运力资源,承运方完成承运履约。
但如果抽象成“撮合需求和资源”,就太空了。它已经无法指导派单、抢单、接人、送达、取消、支付这些具体决策。
业务模式的抽象难点就在这里:抽象不足,会退化成具体业务功能;抽象过度,会失去决策价值。更稳的做法是先建具体模型,再通过角色化变化点做泛化。
真微服务要有业务能力和产品生命周期
课程对微服务的判断很务实。真正的微服务至少要满足三件事:
| 判断点 | 真微服务 | 常见伪形态 |
|---|---|---|
| 服务粒度 | 按业务能力组织 | 只把函数拆成分布式接口 |
| 生命周期 | 服务以产品方式研发和运营 | 多个服务仍按同一个项目节奏一起改 |
| 逻辑位置 | 逻辑集中在服务中,编排简单 | 服务只做 CRUD,复杂逻辑泄漏到编排层 |
不按业务能力拆,只是分布式服务;生命周期绑在一起,是微工作组;服务没有业务能力,只把逻辑丢给编排引擎,是傻服务;一处改动牵连一堆服务,是分布式单体。
把 8X Flow 模型落到微服务时,不要先纠结部署单元。先把合同上下文、履约上下文、领域上下文映射为 API,构建资源和关系。API 代表服务生态里的模型边界。然后再看弹性边界和生命周期是否值得独立部署。
一个服务对消费者的承诺,也不只是接口不变。它还包括版本生命周期、兼容策略、服务质量和运营责任。如果服务团队不能长期维护旧版本,消费者就会被迫跟着升级,微服务会在生命周期上重新耦合。
SaaS 化本质上是选项设计
课程最后谈 SaaS 化,其实是在继续同一条主线:云平台、微服务和开放服务生态最终都会遇到差异化服务质量问题。
传统云化容易假设所有用户共享同一套服务质量。所有快递都按次日达提供,所有咖啡都只有超大杯,这当然能服务用户,但成本会很高。更合理的方式是围绕选项建模。
选项可以理解成:
能力 + 服务质量 = Offering
快递都能把包裹从 A 地送到 B 地,这是能力;当天达、次日达、标快、特惠,是不同服务质量和成本结构。软件服务也一样:能力可能相同,但可用性、隔离性、响应速度、专属支持、数据独享程度可以不同。
魔球 SaaS 选项建模法把客户分成三类:
| 客户类型 | 特征 | 策略 |
|---|---|---|
| 高价值客户 | 重视服务质量和响应速度,愿意支付更高成本 | 独立环境、专属支持、快速满足个性化需求 |
| 现金奶牛 | 覆盖大多数用户,诉求标准化 | 自动化、自助式、共享环境,降低运营成本 |
| 尴尬客户 | 价值不高,成本又降不下来 | 转化为高价值客户或现金奶牛,必要时结束生命周期 |
这套方法也能指导存量系统 SaaS 化。先把现有系统定义为遗留选项,再从用户群体中分化出高价值客户和现金奶牛,用新选项逐步替换旧选项。
SaaS 化的关键不是 Kubernetes 怎么配,而是选项设计是否准确。否则只是把原来的定制项目搬到云上,成本结构并没有变。
拿到一个业务后怎么做
如果把这门课压成一条实践路径,我会这样走:
- 先问业务靠什么赚钱或省钱。内容管理、搜索、推荐、支付这些能力,和定价、订阅、分成、补偿这些运营逻辑,要分开看。
- 找合同上下文。谁和谁之间存在权责?合同怎么成立?主要履约项是什么?每个履约项的权利方、义务方、请求、确认和凭证分别是什么?
- 追违约和补偿。履约失败后发生什么?合同作废、退款、罚息、补偿,还是进入外部法律流程?不要把它们当技术异常。
- 找变化点。哪些履约确认可以由不同凭证扮演?哪些角色可以由不同领域系统扮演?哪些合同上下文之间存在凭证引用?
- 再看架构边界。合同上下文、履约上下文、领域上下文分别有什么弹性诉求?同步调用是否制造弹性耦合?异步后的中间态在业务上意味着什么?
- 最后设计 API 和产品化服务。资源从模型来,URI 表达模型关系,服务要有版本、兼容性、质量和生命周期承诺。
这条路径的重点,是不要从系统边界或服务拆分开始。先从业务本身寻找结构,再把结构映射到技术实现。
几个容易踩偏的地方
不要把 DDD 等同于战术模式。实体、值对象、聚合、仓储只是实现手段。核心是模型、语言、代码和反馈循环是否连在一起。
不要从解决方案反推问题。策略模式、状态模式、中台、微服务、SaaS 都是“问题 + 解法”的组合。只拿解法,会制造认知噪音。
不要为了“领域复用”忽略业务逻辑。商业社会里,复用领域功能不等于复用业务。ERP 的历史已经说明,要么企业流程适配产品,要么产品被大量定制。真正难复用的是业务运营模式。
不要机械按业务上下文拆微服务。云平台上还要看弹性边界。如果拆开不能带来独立扩缩容、独立生命周期或成本收益,拆分只会增加复杂度。
不要把中台理解成共享服务集合。中台的目标是支撑小前台团队快速试错,核心是复用特定场景中的业务模式,而不是沉淀一堆通用 CRUD 能力。
结语
这门课最值得带走的判断,是业务建模不是“画模型”,而是“定义问题”。
DDD 解决的是模型、语言和实现如何互相反馈;事件建模和四色建模解决的是如何把业务过程和凭证链找出来;云时代的弹性边界提醒我们,架构约束会反过来改变模型;8X Flow 则用合同和履约,把业务本来就存在的异步、权责、凭证、变化点和服务边界显式化。
最后仍然回到那句话:先从业务本身寻找结构,再把结构映射到技术实现。不要从技术方案定义业务问题。