【发布时间】:2017-06-07 22:44:16
【问题描述】:
每当我查看Axon Bank 时,我都会开始思考是否应该遵循一组事件和命令的设计规则。
在 Axon Bank 中,事件和命令都完全由原语组成。在我的应用程序中,我倾向于尽可能避免使用原始用法,主要是为了构建一个富有表现力的域并在我能获得的任何地方保持类型安全。
Axon 本身带有一些 DDD 引用,但无论我浏览哪些文档,没有一个示例使用复合对象作为事件/命令负载的一部分。
这让我很困惑。内置对完整的 xml 和 json 序列化的支持,不仅可以拥有一些键值对。
我知道,特别是事件往往是小而简单的结构,因为它们只反映增量状态变化,但复杂的域模型和事件(条目)之间总会存在某种差距。
在我的域中,我可以拥有一堆类,例如 OverdraftLimit、CurrentBalance、Deposit 和 AccountIdentifier。
现在有两种可能的方式来设计事件和命令:
1。基元和广泛的转换
- 将事件视为带有漂亮标签的原始数据
- 在原始数据“进入”应用程序后立即将其转换为强大的对象
-
创建事件时,只需将它们再次剥离即可。
public class BankAccountcreatedEvent { private final String accountIdentifier; private final int overdraftLimt; // ... }还有其他地方:
public void on (BankAccountCreatedEvent event) { this.accountIdentifier = AccountIentifier.fromString(event.getAccountIdentifier()); this.overdraftLimit = new OverdraftLimit(event.getOverdraftLimit()); }
优点:
- 简单的命令/事件 API,没有任何奇怪的依赖关系
- 使分发更容易
- 只有在实际事件结构发生变化时才需要上调者,因此可以轻松预测。
缺点:
- 需要编写和维护一个巨大的转换层
- 主要出于技术原因将事件/命令与域模型的其余部分解耦会引入新的、人为的上下文差距
2。富有表现力的负载
-
直接使用复杂的类型作为属性
public class BankAccountCreatedEvent { private final BankAccountIdentifier bankAccountIdentifier; private final OverdraftLimit overdraftLimit; //.. }
优点:
- 写得更少,读起来更容易
- 自然而然地保持在一起
缺点:
- 领域逻辑会间接影响事件结构,因此需要更频繁地进行向上转换,并且更难以预测。
我需要第二个意见。有推荐的方法吗?
【问题讨论】: