当领域事件发生时,谁对实体的突变负责? DDD

2023-12-10

我一直在学习CQRS/ES。查看我经常看到的小示例项目改变实体状态的事件。例如,如果我们看一下Order 聚合根:

public class Order : AggregateRoot {
    private void Apply(OrderLineAddedEvent @event) {
        var existingLine = this.OrderLines.FirstOrDefault(
            i => i.ProductId == @event.ProductId);

        if(existingLine != null) {
            existingLine.AddToQuantity(@event.Quantity);
            return;
        }

        this.OrderLines.Add(new OrderLine(@event.ProductId, @event.ProductTitle, @event.PricePerUnit, @event.Quantity));
    }

    public ICollection<OrderLine> OrderLines { get; private set; }

    public void AddOrderLine(/*parameters*/) {
        this.Apply(new OrderLineAddedEvent(/*parameters*/));
    }

    public Order() {
        this.OrderLines = new List<OrderLine>();
    }

    public Order(IEnumerable<IEvent> history) {
        foreach(IEvent @event in history) {
            this.ApplyChange(@event, false);
        }
    }
}

public abstract class AggregateRoot  {
    public Queue<IEvent> UncommittedEvents { get; protected set; }

    protected abstract void Apply(IEvent @event);

    public void CommitEvents() { 
        this.UncommittedEvents.Clear();
    }

    protected void ApplyChange(IEvent @event, Boolean isNew) {
        Apply(@event);
        if(isNew) this.UncommittedEvents.Enqueue(@event);
    }
}

when OrderLineAddedEvent应用它会发生变异Order通过添加新订单行。但我不明白这些事情:

  • 如果这是正确的方法,那么所做的更改如何持久?
  • 或者我应该以某种方式将事件发布到相应的处理程序Order?我如何在技术上实现这一点?我应该使用服务总线来传输事件吗?

我还在尝试 ES,所以这仍然是一种意见,而不是任何指导:)

在某个阶段,我看到了 Jan Kronquist 的这篇文章:http://www.jayway.com/2013/06/20/dont-publish-domain-events-return-them/

其要点是事件应该从域返回,而不是从域内调度。这确实引起了我的共鸣。

如果一个人要多拿一份传统的使用普通的面向持久性的存储库的方法应用层将处理事务和存储库访问。只需调用该域即可执行该行为。

此外,领域应该始终坚持持久性无知。让一个聚合根维护一个事件列表对我来说总是有点奇怪,而且我绝对不喜欢让我的 AR 继承一些公共基础。感觉不够干净。

因此,使用您拥有的资源将其组合在一起:

public OrderLineAddedEvent AddOrderLine(/*parameters*/) {
    return this.Apply(new OrderLineAddedEvent(/*parameters*/));
}

在我的 POC 中,我也没有使用过IEvent标记接口而只是一个object.

Now the 应用层又恢复了对持久性的控制。

我有一个实验性的 GitHub 存储库:

  • https://github.com/Shuttle/shuttle-recall-core
  • https://github.com/Shuttle/shuttle-recall-sqlserver

我已经有一段时间没有时间查看它了,我知道我已经做了一些更改,但欢迎您查看。

基本思想是应用层将使用EventStore/EventStream以与管理聚合事件相同的方式应用层会使用一个Repository. The EventStream将应用于聚合。从域行为返回的所有事件都将添加到EventStream之后它再次持续存在。

这将所有面向持久性的位保留在域之外。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当领域事件发生时,谁对实体的突变负责? DDD 的相关文章

  • 每个托管线程是否都有自己对应的本机线程?

    我想知道是否在 Net 中创建托管线程 通过调用Thread Start 导致在后台创建一个本机线程 那么托管线程是否有对应的本机线程呢 如果是 当托管线程等待或睡眠时 是否意味着相应的本机线程也在等待或睡眠 是的 NET 线程映射到所有当
  • 注销租约抛出 InvalidOperationException

    我有一个使用插件的应用程序 我在另一个应用程序域中加载插件 我使用 RemoteHandle 类http www pocketsilicon com post Things That Make My Life Hell Part 1 App
  • 如何在 .NET Framework 2.0 中模拟“Func<(Of <(TResult>)>) 委托”?

    我尝试使用这个类代码项目文章 http www codeproject com KB threads AsyncVar aspx在 VB NET 和 NET Framework 2 0 中 除了这一行之外 所有内容似乎都可以编译Privat
  • 如何将非静态类成员“std::bind”绑定到 Win32 回调函数“WNDPROC”?

    我正在尝试将非静态类成员绑定到标准WNDPROC http msdn microsoft com en us library ms633573 aspx功能 我知道我可以通过将类成员设为静态来简单地做到这一点 但是 作为一名 C 11 ST
  • 获取两个工作日之间的天数差异

    这听起来很简单 但我不明白其中的意义 那么获取两次之间的天数的最简单方法是什么DayOfWeeks当第一个是起点时 如果下一个工作日较早 则应考虑在下周 The DayOfWeek 枚举 http 20 20 5B1 5D 3a 20htt
  • 回发后刷新时提示确认表单重新提交。我做错了什么?

    我有一个以空白 默认状态启动的仪表板 我让用户能够将保存的状态加载到仪表板中 当他们单击 应用 按钮时 我运行以下代码 function CloseAndSave var radUpload find radUpload1ID var in
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 为什么调用非 const 成员函数而不是 const 成员函数?

    为了我的目的 我尝试包装一些类似于 Qt 共享数据指针的东西 经过测试 我发现当应该调用 const 函数时 会选择它的非 const 版本 我正在使用 C 0x 选项进行编译 这是一个最小的代码 struct Data int x con
  • 从 Linux 内核模块中调用用户空间函数

    我正在编写一个简单的 Linux 字符设备驱动程序 以通过 I O 端口将数据输出到硬件 我有一个执行浮点运算的函数来计算硬件的正确输出 不幸的是 这意味着我需要将此函数保留在用户空间中 因为 Linux 内核不能很好地处理浮点运算 这是设
  • 标准化 UTF-8 到底是什么?

    The 重症监护室项目 http userguide icu project org transforms normalization 现在也有一个PHP库 http us php net manual en class normalize
  • DbContext 和 ObjectContext 有什么区别

    From MSDN 表示工作单元和存储库模式的组合 使您能够查询数据库并将更改分组在一起 然后将这些更改作为一个单元写回存储 DbContext在概念上类似于ObjectContext 我虽然DbContext只处理与数据库的连接以及针对数
  • 如何检测表单的任何控件的变化?

    如何检测 C 中表单的任何控件的更改 由于我在一个表单上有许多控件 并且如果表单中的任何控件值发生更改 我需要禁用按钮 我正在寻找一些内置函数 事件处理程序 属性 并且不想为此创建自定义函数 不 我不知道任何时候都会触发任何事件any控制表
  • C# 中的合并运算符?

    我想我记得看到过类似的东西 三元运算符 http msdn microsoft com en us library ty67wk28 28VS 80 29 aspx在 C 中 它只有两部分 如果变量值不为空 则返回变量值 如果为空 则返回默
  • 外键与独立关系 - Entity Framework 5 有改进吗?

    我读过了several http www ladislavmrnka com 2011 05 foreign key vs independent associations in ef 4 文章和问题 https stackoverflow
  • 如何设置 log4net 每天将我的文件记录到不同的文件夹中?

    我想将每天的所有日志保存在名为 YYYYMMdd 的文件夹中 log4net 应该根据系统日期时间处理创建新文件夹 我如何设置它 我想将一天中的所有日志保存到 n 个 1MB 的文件中 我不想重写旧文件 但想真正拥有一天中的所有日志 我该如
  • Cmake 链接共享库:包含库中的头文件时“没有这样的文件或目录”

    我正在学习使用 CMake 构建库 构建库的代码结构如下 include Test hpp ITest hpp interface src Test cpp ITest cpp 在 CMakeLists txt 中 我用来构建库的句子是 f
  • 如何在非控制台应用程序中查看 cout 输出?

    输出到调试窗口似乎相当繁琐 我在哪里可以找到cout如果我正在编写非控制台信息 则输出 Like double i a b cout lt lt b lt lt endl I want to check out whether b is z
  • 调用堆栈中的“外部代码”是什么意思?

    我在 Visual Studio 中调用一个方法 并尝试通过检查调用堆栈来调试它 其中一些行标记为 外部代码 这到底是什么意思 方法来自 dll已被处决 外部代码 意味着该dll没有可用的调试信息 你能做的就是在Call Stack窗口中单
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中
  • 当从finally中抛出异常时,Catch块不会被评估

    出现这个问题的原因是之前在 NET 4 0 中运行的代码在 NET 4 5 中因未处理的异常而失败 部分原因是 try finallys 如果您想了解详细信息 请阅读更多内容微软连接 https connect microsoft com

随机推荐