防腐层
防腐层用于隔离外部模型与内部领域模型污染的模式说明
#status / growing
#type / concept
#tech / dev
防腐层 Anti-Corruption Layer (ACL)
一句话定义
防腐层是 DDD 中的一个适配层,位于自己的限界上下文与外部系统之间,负责将外部模型翻译为内部领域模型,防止外部概念污染核心域。
核心机制 / 工作原理
为什么需要防腐层
- 遗留系统集成 — 老系统的数据模型往往混乱、过时,直接暴露给新系统会污染新领域模型
- 第三方 API — 外部服务的模型随时可能变化,ACL 提供隔离屏障
- 限界上下文边界 — 不同团队维护的上下文有不同的领域语言,ACL 负责翻译
工作原理
内部领域模型 <--> 防腐层 (ACL) <--> 外部系统模型
Order Translator LegacyOrderDTO
ACL 内部包含:
- Facade — 简化外部系统的复杂接口
- Adapter — 调用外部系统的 API
- Translator — 将外部模型转换为内部领域对象
数据流:内部调用 ACL -> ACL 通过 Adapter 调用外部系统 -> Translator 将返回值转为内部模型 -> 返回给内部调用方。
最小例子
// 外部遗留支付系统返回的结构
public class LegacyPaymentResponse {
public int status_code; // 1=成功, 0=失败
public String txn_id;
public double amount_cents; // 以分为单位
}
// 我们的领域模型
public class PaymentResult {
PaymentStatus status; // SUCCESS, FAILED
String transactionId;
Money amount; // 包含币种的金额对象
}
// 防腐层 —— 翻译器
public class LegacyPaymentACL {
private final LegacyPaymentClient client;
public PaymentResult charge(Order order) {
LegacyPaymentResponse resp = client.pay(
order.getAmount().getCents(),
order.getPaymentRef()
);
// 翻译:外部模型 -> 内部模型
return new PaymentResult(
resp.status_code == 1 ? PaymentStatus.SUCCESS : PaymentStatus.FAILED,
resp.txn_id,
Money.fromCents(resp.amount_cents)
);
}
}
核心域代码只依赖 PaymentResult,完全不知道 LegacyPaymentResponse 的存在。
边界与常见误解
- “ACL 只是做数据转换” — 不只是转换。ACL 封装了外部系统的协议、调用方式、错误处理,使核心域完全不感知外部系统的存在。
- “所有外部调用都需要 ACL” — 不是。如果外部系统的模型与你的领域模型高度一致,直接集成更简单。ACL 用于模型差异大或外部系统不可控的场景。
- ACL vs API Gateway — API Gateway 是入口层(面向客户端),ACL 是出口层(面向外部服务),方向相反。
- ACL 会增加延迟吗 — 多一层调用确实有微量开销,但可忽略。价值在于隔离和可维护性。
- ACL 放在哪里 — 通常放在防腐层自己的模块/包中,作为限界上下文的一部分,而不是独立服务。
related notes
- 相关知识: 防腐层哪里使用, DDD架构, ddd中领域服务和应用服务
- [[ddd-bounded-context|限界上下文]]
- [[adapter-pattern|适配器模式]]