3. 业务驱动架构:如何从业务需求推导出技术架构?领域驱动设计(DDD)入门

很多团队做架构,上来就画技术栈。Spring Cloud、Redis、Kafka…… 图很漂亮,但上线后业务方说「这不是我要的」。为什么会这样?

说白了,你跳过了最关键的一步:从业务需求推导出技术架构。技术架构不是凭空想出来的,它应该是业务模型的自然映射。今天我们就聊聊怎么做到这一点,以及领域驱动设计(DDD)在其中扮演的角色。

3.1 业务需求到技术架构的推导路径

我习惯把推导路径分成四步。每一步都有明确的产出物,避免「拍脑袋」做决策。

步骤 输入 产出物 核心问题
1. 业务愿景分析 产品愿景、用户故事 核心业务目标、关键指标 系统要解决什么根本问题?
2. 业务场景梳理 用户旅程、业务流程 用例图、事件风暴结果 谁在什么场景下做什么?
3. 领域建模 用例、业务规则 限界上下文、聚合、实体 业务的核心概念和关系是什么?
4. 技术架构映射 领域模型、非功能需求 微服务拆分、模块划分、技术选型 模型如何落地为代码和部署单元?

你看,前三步都是业务侧的。技术架构是最后一步。顺序不能乱。

我曾经犯过的错: 在一个电商项目中,我直接按「用户服务、订单服务、商品服务」拆了微服务。结果订单服务里塞满了促销逻辑,促销又依赖用户等级…… 最后改得痛不欲生。后来才明白,微服务的边界应该由业务领域决定,而不是技术分层。

3.2 领域驱动设计(DDD)的核心概念

DDD 不是什么新东西。Eric Evans 在 2003 年就写了那本蓝皮书。但直到微服务火了,大家才重新捡起来。为什么?因为 DDD 的限界上下文,天然就是微服务的拆分边界。

DDD 有两个阶段:战略设计 和 战术设计。战略设计解决「切分」问题,战术设计解决「实现」问题。我们重点讲战略设计,因为这是架构师最常用的。

3.2.1 限界上下文(Bounded Context)

这是 DDD 最核心的概念。一个限界上下文就是一个语义边界。在边界内,每个业务术语都有明确的、唯一的含义。

举个例子,「用户」这个词:

  • 在订单上下文里,「用户」是「下单人」,有收货地址、支付方式。
  • 在客服上下文里,「用户」是「服务对象」,有投诉记录、满意度评分。
  • 在财务上下文里,「用户」是「账户主体」,有余额、账单。

同一个「用户」,在不同上下文里,关心的属性完全不同。如果你强行用一个 User 表搞定所有,那这个表会膨胀到几百个字段,谁也看不懂。

我的判断方法: 如果两个团队对同一个业务术语的理解有分歧,那它们大概率属于不同的限界上下文。这时候别争论谁对谁错,直接拆开。

3.2.2 实体(Entity)与值对象(Value Object)

这两个概念容易混淆。我简单说说区别:

特征 实体(Entity) 值对象(Value Object)
是否有唯一标识 是(ID 决定身份) 否(属性决定相等)
是否可变 可变(生命周期内属性可改) 不可变(替换而非修改)
典型例子 订单、用户、商品 金额、地址、颜色

你想想看,两个订单即使金额一样,也是不同的订单(实体)。但两个「北京市朝阳区」的地址,如果属性完全一样,就是同一个地址(值对象)。

3.2.3 聚合(Aggregate)

聚合是一组相关对象的集合,由聚合根统一管理。外部只能通过聚合根来访问聚合内的对象。

比如「订单」聚合:

  • 聚合根:订单(Order)
  • 内部对象:订单项(OrderItem)、支付记录(Payment)
  • 规则:不能直接修改订单项,必须通过订单对象来操作

这样做的好处是保证数据一致性。所有修改都经过聚合根,不会出现「订单已取消,但订单项还在发货」的诡异情况。

3.3 事件风暴:快速发现领域模型

理论说完了,怎么落地?我个人最推荐的方法是事件风暴(Event Storming)。这是 Alberto Brandolini 发明的 workshop 技术,特别适合在项目启动阶段用。

操作很简单:

  1. 准备材料: 一面大墙、不同颜色的便利贴、马克笔。
  2. 找对人: 业务专家、产品经理、开发、测试,围在一起。
  3. 开始贴:
    • 橙色便利贴:领域事件(已经发生的事情,如「订单已支付」)
    • 蓝色便利贴:命令(触发事件的动作,如「提交支付」)
    • 绿色便利贴:聚合(执行命令的对象,如「订单」)
    • 红色便利贴:外部系统(如「支付网关」)

我记得在一个金融项目中,我们用事件风暴梳理「开户」流程。业务方说「很简单啊,填表提交就行」。结果贴了半小时,发现涉及反洗钱检查、征信查询、风险评级、额度分配…… 整整 20 多个事件。如果直接写代码,肯定漏掉一半。

事件风暴的核心价值: 它让业务方和技术方在同一个房间里,用同一套语言(便利贴)讨论问题。你不需要懂 UML,不需要画时序图。一张便利贴就是一个概念,所有人都能参与。

3.4 从领域模型到微服务架构

模型建好了,怎么变成微服务?

原则很简单:一个限界上下文,对应一个微服务(或一个模块)。

但要注意,不是所有限界上下文都要拆成独立服务。我一般这样判断:

条件 建议 原因
上下文之间频繁通信 合并为一个服务 避免分布式事务的复杂度
上下文有独立的生命周期 拆分为独立服务 可以独立部署、独立扩展
上下文需要不同的技术栈 拆分为独立服务 技术异构,解耦
团队规模小(< 10人) 先合并,后拆分 过早拆分增加运维成本

嗯,这里要注意:微服务不是越细越好。我见过一个项目拆了 50 多个服务,结果每次上线要协调 30 个团队。那已经不是架构了,是灾难。

3.5 知识体系总览

下面这张图总结了本章的核心逻辑:从业务需求出发,经过 DDD 战略设计,最终落地为技术架构。

业务驱动架构:从需求到技术架构的推导路径 业务愿景 & 用户故事 核心目标 / 关键指标 业务场景梳理 用户旅程 / 事件风暴 非功能需求 性能 / 可用性 / 安全 DDD 战略设计(领域建模) 限界上下文 → 实体 / 值对象 → 聚合 → 领域事件 产出:领域模型(统一语言 + 边界划分) 技术架构映射 微服务拆分 / 模块划分 / 技术选型 产出:架构设计文档 + 代码骨架 可交付的架构方案 核心原则:技术架构是业务模型的自然映射,不要跳过领域建模直接选技术

3.6 避坑指南

最后分享几个我踩过的坑:

  • 不要试图用 DDD 覆盖所有模块。 简单的 CRUD 模块,用传统三层架构就够了。DDD 适合业务逻辑复杂的核心域。
  • 统一语言不是一次性的。 我见过团队在启动会上定了术语,三个月后代码里全是新名词。要定期和业务方对齐。
  • 聚合不要设计得太大。 一个聚合包含几十个实体,性能会出问题。我一般控制在 3-5 个对象以内。
  • 事件风暴的产出要立刻归档。 便利贴贴完不拍照、不整理,第二天就忘了。我习惯当天晚上就转成电子版。

业务驱动架构,说白了就是让技术回归本质:为业务服务。DDD 提供了一套工具,帮你把模糊的业务需求,变成清晰的、可落地的技术方案。下次接到新需求,别急着打开 IDE。先找业务方聊一聊,贴一贴便利贴。你会发现,很多问题在画图阶段就已经解决了。