04 业务与业务粒度
电商业务流程的粒度划分¶
第一级:属性级 (单表,单字段)¶
最小单元,原子状态跃迁
- 操作:对一个实体的一个状态字段做条件更新。
- 典型例子:
签收:UPDATE shipment SET status = 'SIGNED'已读:UPDATE notification SET is_read = 1取消:UPDATE order SET status = 'CANCELLED'- 本质:一个业务行动的最小粒度。它不关心其他实体,只完成自己核心的那个“事儿”。
第二级:连接级 (双表关联)¶
常见查询与一对一的写入
- 操作:围绕一个核心实体,建立或查询其唯一的附属信息。
- 典型例子:
付款:创建支付单,并与订单绑定 →订单表1 : 1支付表发货:创建物流单,并与订单绑定 →订单表1 : 1物流表退款:创建退款单,关联原支付单。- 在数据库设计上,这是一种垂直拆分,用于扩展核心实体。读是两表Join,写是先写子表,再更新主表状态。
第三级:事务级 (多表连接)¶
一个写操作,多个实体联动
- 操作:需要在一个事务内,同时操作两个以上的实体,保证数据一致性。
- 典型例子:
- 下单:用户表(校验) → 商品表(扣库存) → 订单头(生成) → 订单行(快照) → 优惠券(核销)。
- 拆单发货:一个订单,生成多个物流单,库存要对应扣减。
- 本质:这是一个跨聚合的领域编排。你不再是一个简单的状态机,而是一个复杂的状态流转协调器。
第四级:流程级 (长流程,状态机)¶
端到端的长业务流
- 操作:由多个有序的阶段(每个阶段都是一个“连接级”或“事务级”操作)串联而成的完整生命周期。
- 典型例子:
- 下单 → 付款 → 发货 → 签收 → 完成:这就是一个典型的订单状态机的一次完整旅程。
- 本质:这是业务最大的粒度。它定义了实体从生到死的完整路径,每一步都是上述三个级别操作之一的触发和结果。
购物系统中一个订单完整的业务流程(核心里程碑状态流转):
stateDiagram-v2
[*] --> 待支付
待支付 --> 已支付 : 用户付款成功
已支付 --> 已发货 : 商家发货,快递揽收
已发货 --> 已签收 : 物流派送,用户签收
已签收 --> 已完成 : 订单完成(确认收货/超时自动)
待支付 --> 已取消 : 超时未付/用户取消
已支付 --> 退款中 : 用户申请退款
已发货 --> 退货中 : 用户申请退货
退货中 --> 退款中 : 退货签收,商家确认
退款中 --> 已退款 : 退款到账
已取消 --> [*]
已完成 --> [*]
已退款 --> [*]
图上展示的就是纯粹的业务流程主线与分支:
- 正常路径:下单 → 付款 → 发货 → 签收 → 完成
- 取消路径:待支付时主动或超时取消
- 逆向流程:已支付可申请退款;已发货可申请退货,之后再退款
总结¶
属性修改 → 两表连接 → 多表事务 → 全流程,是把业务流程从微观的写操作,经中观的实体关联,到宏观的生命周期管理,进行了完美的抽象。它既是理解业务的“粒度标尺”,也是指导架构解耦和领域划分的“设计光谱”。
-
职责边界清晰化
- 属性级的操作,应该内聚在实体内,方法就是
entity.sign()。 - 连接级的操作,适合做成一对一的领域服务,如
PaymentService.createFor(order)。 - 事务级的操作,需要应用服务/用例层来编排多个领域服务,并管理事务。
- 属性级的操作,应该内聚在实体内,方法就是
-
发现解耦的机会
- 如果你发现一个“连接级”操作(付款),总是与另一个“事务级”操作(下单)耦合出现,你就可以思考:它们真的必须同步完成吗?
- 答案是:通常不。于是就有了 异步解耦(付款通过消息触发后续流程),把一个事务级的大动作,拆成一个属性级触发 + 一个异步事件。
-
评估重构的复杂度
- 想要把“属性级”重构为“连接级”(比如给签收增加一个图片凭证子表),复杂度可控。
- 想要把一个同“连接级”的同步核心路径操作拆解成异步,则是架构性的重构,需要仔细设计状态机中间态和回滚策略。