核心在于分层定义职责:状态契约层专注声明不可变状态与转换函数,业务层仅消费状态,通过适配器隔离传输与持久层,确保状态变更可追溯、可审计、无副作用。

核心变量逻辑与业务逻辑强拆分,关键不在“分开写”,而在“分层定义职责”——变量不是数据容器,而是系统状态的契约表达;业务不是流程脚本,而是对状态变化的响应与约束。这种拆分不是为了增加模块数量,而是让谁负责定义“什么可变、如何变、为何变”变得清晰可追溯。
明确变量层的定位:状态契约层
变量不应散落在Service、Controller甚至DTO中,而应集中定义在独立的状态契约层(常命名为 State 或 DomainModel 层)。这一层只做三件事:
- 声明领域内不可绕过的状态实体(如 OrderStatus、InventoryLockType、CommissionRule),不带任何行为或校验逻辑
- 用不可变结构(如 Java 的 record、TypeScript 的 readonly interface)封装关键状态组合,避免运行时意外篡改
- 所有状态变更必须通过明确定义的“状态转换函数”(如
nextStatus(current: OrderStatus, event: 'pay' | 'cancel'))驱动,该函数只在此层定义,不实现业务规则
业务逻辑层只消费状态,不定义状态
Service 层或领域服务(Domain Service)只能读取、传递、响应状态,但绝不能新增、修改或推导状态定义。例如:
- 订单支付成功后,调用
StatusTransition.next(OrderStatus.PAID, 'pay')获取新状态,而不是直接写order.status = 'PAID' - 佣金计算服务接收
CommissionRule实例作为参数,不自行构造规则对象,也不解析其内部字段含义 - 权限判断逻辑依赖
RoleType.ADMIN这类枚举值,但不硬编码字符串或数字,更不把角色判断逻辑塞进 RoleType 类里
引入状态生命周期管理器(可选但推荐)
当状态流转存在多步、条件分支或需审计时,可增设轻量级状态管理器(如 OrderStateManager),它:
- 持有当前状态实例和历史快照(仅用于追溯,不参与决策)
- 对外暴露
apply(event)接口,内部委托给状态契约层的转换函数 - 触发领域事件(如
StatusChangedEvent),由业务监听器执行后续动作(发通知、更新库存、生成账单) - 自身不包含 if-else 业务分支,所有分支逻辑下沉到监听器或策略服务中
接口与传输层严格隔离状态表达
表现层(Controller/API)和数据访问层(DAO/Repository)都不得直接引用状态契约类的实现细节:
- API 入参用 DTO 接收原始字段(如
{ status: 'paid' }),由适配器(Adapter)转为OrderStatus.PAID后交由状态管理器处理 - 数据库存储用简单字段(如
status_code VARCHAR),DAO 层负责映射到契约层枚举,不暴露枚举类给持久层 - 前端传来的状态标识必须经过白名单校验(如只允许 'draft', 'paid', 'shipped'),校验逻辑放在适配器,不在契约层或业务层重复判断










