处理Axon

时间:2017-05-30 16:16:46

标签: java spring axon

每当我看一下Axon Bank时,我就开始想知道是否应该遵循一套事件和命令的设计规则。

在Axon Bank中,事件和命令都只包含基元。在我的应用程序中,我倾向于尽可能地避免原始用法,主要是为了建立一个富有表现力的域,并在任何地方都能获得类型安全。

Axon本身带来了一些DDD引用,但无论我浏览哪些文档,没有一个示例使用复合对象作为事件/命令有效负载的一部分。

让我感到困惑。内置支持完整的xml和json序列化,不仅能够拥有一些键值对。

我理解特别是事件往往是小而简单的结构,因为它们只反映增量状态变化,但复杂域模型和事件(条目)之间总会存在某种差距。

在我的域名中,我可以拥有一堆类,例如OverdraftLimitCurrentBalanceDepositAccountIdentifier

现在有两种可能的方法来设计事件和命令:

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;
    
        //..
    }
    

优点:

  • 写得少,易于阅读
  • 将自然属于的东西放在一起

缺点:

  • 域逻辑间接影响事件结构,需要更频繁地进行向上转换,并且不太可预测。

我需要第二个意见。有推荐的方法吗?

1 个答案:

答案 0 :(得分:1)

要记住的主要事情是事件的序列化形式是您的正式合同。在Java类中如何表示它最终取决于每个应用程序。如果将序列化程序配置为忽略未知字段,则可以保留不关心的字段,例如。

就个人而言,我不介意事件中的原语。但是,我确实理解为某些字段使用显式值对象的价值,因为它们允许您表达每个字段所涉及的“数学”。在标识符的情况下,它们会阻止使用标识符意外尝试识别其他类型对象的“混淆”。

最后,这并不重要。通过一些简单的Jackson注释,您可以将这些值对象转换为JSON中的简单值。例如,请查看@JsonValue

public class BankAccountCreatedEvent {
    private final BankAccountIdentifier bankAccountIdentifier;
    private final OverdraftLimit overdraftLimit;

    //..
}

将映射到:

{
    "bankAccountIdentifier": "abcdef1234",
    "overdraftLimit" : 1000
}

如果BankAccountIdentifier和OverdraftLimit类都有一个@JsonValue注释方法,它将返回它们的“简单”值。