跳至主要內容

副作用驱动设计体系(Effect-Driven Design, EDD)

Mr.Lexon大约 4 分钟EDD

Title

副作用驱动设计体系(Effect-Driven Design, EDD)

一、设计哲学

副作用驱动设计(Effect-Driven Design, EDD)是一种以“副作用识别与组织”为核心的系统架构方法。它不以MVC、DDD等传统技术结构为起点,而以副作用的边界、风险和组织方式为第一性原则,构建适应变化、具备可观测性和可测试性的现代系统。

核心口号:副作用不可怕,不可控的副作用才可怕。

二、核心构成模块

层级内容说明
core/纯业务数据结构与逻辑不允许副作用,可100%测试
domain/行为语义接口定义(trait)(行为定义层)描述副作用语义,不绑定具体框架
app/usecase编排层(这个其实应该是Service层)组合 trait、协调行为、返回结果+事件
infra/具体实现,如 DB/API/Cache (这个是副作用实现层)所有副作用实现汇聚于此层
event/事件定义与事件调度器 (这是副作用触发层)用于解耦外部副作用与主流程
代码模板结构:
edd-template/
├── src/
│   ├── core/           # 纯逻辑与模型定义
│   ├── domain/         # trait 抽象接口
│   ├── app/            # usecase 调用与事件组织
│   ├── infra/          # SeaORM 数据库实现、EventDispatcher
│   ├── event/          # AppEvent + OutboxManager
│   └── main.rs         # 项目入口
├── migrations/         # SeaORM migration 模板
├── README.md
├── Cargo.toml
└── template.toml       # cargo-generate metadata

三、副作用评判标准(Effect Heuristics)

维度问题高风险信号建议
影响范围是否改变状态?写库、调用RPC用 trait 封装
可测性是否能mock?外部网络/环境/时间依赖分离纯逻辑 + 抽象副作用层
幂等性重复调用是否影响?积分重复发、重复入账接入幂等键 / 事件幂等控制
顺序敏感性调用顺序是否重要?发券→发通知引入队列 / job scheduler
用户感知性失败是否对用户可感知?没有收到欢迎邮件记录日志或提升为事件
失败代价失败是否需要补偿?扣款、业务激活用事件队列确保最终一致

四、usecase输出模型

pub struct Outcome<T> {
    pub data:T,
    pub from_case:AppUseCase,
    pub events:Vec<AppEvent>
}

usecase 中只进行数据库写入与业务流程判断, 所有发消息、发积分、第三方通知等副作用行为转化为 AppEvent,由外部 orchestrator 异步处理。

五、事件设计范式(Outbox Pattern)

outbox 表结构

CREATE TABLE outbox_events (
  id UUID PRIMARY KEY,
  event_type TEXT NOT NULL,
  payload JSONB NOT NULL,
  created_at TIMESTAMP DEFAULT now(),
  dispatched BOOLEAN DEFAULT FALSE
);

消费器 worker

// 每5秒轮询未发送事件并调度

六、副作用分类与架构策略

类型示例架构建议
决策副作用用户是否黑名单、查重trait 注入 + mockable
执行副作用发积分、发消息usecase 内记录 event,outbox 外发
异步非关键副作用日志、埋点、追踪用完即删,记录失败不处理
外部状态操作三方API、风控策略调用异步 + 幂等,必要时引入补偿机制
时间/上下文依赖now()、UUID、request-ip抽象 Clock / IdGenerator / ContextProvider trait (问题同上)

七、开发流程指南

  1. 识别 usecase 的副作用点
  2. 将所有副作用提炼为 trait 或 event
  3. 保持 usecase 的 async fn input -> Outcome<T> 签名,必要时,需要套上一个AppResult.
  4. 用事件调度器处理外发任务
  5. 编写单元测试 + integration test + event replay 测试

八、副作用治理优先级矩阵(简化)

优先级特征示例建议
P0失败即破坏业务扣款、发票事务+幂等+事件重放
P1有失败影响但可补偿发积分、发通知Outbox + 重试机制
P2用户无感知打点、埋点fire-and-forget,无需回滚

九、结语

Effect-Driven Design 不替代传统分层架构,但它提供了副作用识别、组织与调度的第一性方法论,是未来以异步+分布式+高一致性为常态的系统中重要的架构思想补充。


上次编辑于:
贡献者: lexon