每当我看一下Axon Bank时,我就开始想知道是否应该遵循一套事件和命令的设计规则。
在Axon Bank中,事件和命令都只包含基元。在我的应用程序中,我倾向于尽可能地避免原始用法,主要是为了建立一个富有表现力的域,并在任何地方都能获得类型安全。
Axon本身带来了一些DDD引用,但无论我浏览哪些文档,没有一个示例使用复合对象作为事件/命令有效负载的一部分。
让我感到困惑。内置支持完整的xml和json序列化,不仅能够拥有一些键值对。
我理解特别是事件往往是小而简单的结构,因为它们只反映增量状态变化,但复杂域模型和事件(条目)之间总会存在某种差距。
在我的域名中,我可以拥有一堆类,例如OverdraftLimit
,CurrentBalance
,Deposit
和AccountIdentifier
。
现在有两种可能的方法来设计事件和命令:
创建事件时,只需将其再次删除即可。
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());
}
优点:
缺点:
直接使用复杂类型作为属性
public class BankAccountCreatedEvent {
private final BankAccountIdentifier bankAccountIdentifier;
private final OverdraftLimit overdraftLimit;
//..
}
优点:
缺点:
我需要第二个意见。有推荐的方法吗?
答案 0 :(得分:1)
要记住的主要事情是事件的序列化形式是您的正式合同。在Java类中如何表示它最终取决于每个应用程序。如果将序列化程序配置为忽略未知字段,则可以保留不关心的字段,例如。
就个人而言,我不介意事件中的原语。但是,我确实理解为某些字段使用显式值对象的价值,因为它们允许您表达每个字段所涉及的“数学”。在标识符的情况下,它们会阻止使用标识符意外尝试识别其他类型对象的“混淆”。
最后,这并不重要。通过一些简单的Jackson注释,您可以将这些值对象转换为JSON中的简单值。例如,请查看@JsonValue。
public class BankAccountCreatedEvent {
private final BankAccountIdentifier bankAccountIdentifier;
private final OverdraftLimit overdraftLimit;
//..
}
将映射到:
{
"bankAccountIdentifier": "abcdef1234",
"overdraftLimit" : 1000
}
如果BankAccountIdentifier和OverdraftLimit类都有一个@JsonValue注释方法,它将返回它们的“简单”值。