问题标签 [domain-events]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
1500 浏览

module - DDD:放置领域事件的位置

我刚刚阅读了 Vernon 的书“实现领域驱动设计”。我找不到的是把你的领域事件的类放在哪里

  • 在与您的聚合相同的命名空间中?
  • 在像<aggregate-namespace>.Events?
  • 或 hybird:相同的命名空间但物理Events子目录

这不是一个大问题,但很高兴知道你们中的一些人做了什么以及结果如何。

提前致谢!

0 投票
1 回答
173 浏览

oop - 分离域事件的事件监听器?或如何停止在特定用例上执行其他需要的发布事件

因此,让我们以通常的 Order 示例为例。假设有一个富域模型,我们有一个 Order.place() 调用。这些天来执行与此操作相关的其他任务的方法似乎指向域事件。因此,假设此调用触发了“OrderPlaced”事件。放置事件后通常发生的事情是我们发送一封确认电子邮件,因此我们为此事件创建一个事件侦听器,并发送一封电子邮件。

很简单:Order.place() > 引发 OrderPlaced 事件 > EmailForOrderPlaced 监听器触发 > 电子邮件被发送

我们还有以类似方式工作的注册(User.register() > UserRegistered event raises > Registration listener fires > Email gets sent)

然而:

问题(一个虚构的任务 - 不一定有意义 - 但是很多实际的业务需求无论如何都没有):

现在我们希望将注册+订单功能合二为一,与常规的每次注册一封电子邮件+一封订单电子邮件相反,我们只想发送一封包含两者的电子邮件。这是一个复杂的问题,因此通常我们会创建一个域服务来执行此操作,但是如果我们调用 User.register(); 订单.place(); 现在它将像往常一样触发 2 个事件,向客户发送垃圾邮件(好吧,不是真的,但这是一个示例)

那么我们如何解决这个问题呢?显然,发送合并的电子邮件不是问题,因为我们可以在服务中为此引发事件,但这仍然给我们留下了原始的 2 封电子邮件。如果我在执行 2 个调用之前分离服务中的 2 个侦听器,那实际上意味着我必须了解它们的功能,并且每次添加新的侦听器时,我都必须返回服务分离那个,等等,有没有更好的方法可以无缝地做到这一点?

0 投票
6 回答
19682 浏览

domain-driven-design - 在 DDD 中的两个限界上下文之间进行通信

我在域中几乎没有不同的限界上下文。CRUD 操作的验证建立在每个有界上下文中。

例如,只有当创建它的人是 Group Leader 时,我才能创建一个名为 GAME 的实体

在此示例中,我有两个限界上下文 (BC)。一个是Game BC,另一个是User BC。为了解决这个问题,在Game BC中,我必须在继续创建游戏之前对User BC进行域服务调用,例如IsGroupLeader() 。

我不认为 DDD 推荐这种类型的通信。我也可以在Game BC中有一个User 实体,但我不想这样做,因为相同的User 实体在不同的 BC 的不同上下文中的使用方式不同。

我的问题是:

  1. 我应该使用游戏 BC必须向用户 BC发送事件询问用户状态的域事件吗?使用这种方法,我不会像IsGroupLeader那样进行同步调用,而是调用is_group_leader的事件。然后 Game BC 必须等待 User BC 处理事件并返回状态。Game BC 只有在 User BC 处理完事件后才会创建 Game 实体。

  2. CQRS 能解决我的问题吗?

任何想法表示赞赏。

0 投票
1 回答
414 浏览

concurrency - 什么时候使用域事件?

在 DDD 中,我想知道何时应该使用域事件?有适合使用领域事件的情况推荐吗?是否仅适用于最终一致可以接受的情况?

假设在具有 Product、Order、OrderLine 的在线商店示例中,一个 Order 包含多个 OrderLine。一个 OrderLine 和 Product 是一对一的关系,当我创建一个订单的同时,我需要扣除 Product 中的可用金额。我知道有两种方法:

  1. 在 OrderService(应用程序服务)中:

    • 创建一个新订单,插入数据库
    • 对于 Order 中的每个订单行,获取与该 OrderLine 关联的产品,调用 Product.UpdateQuantity()
    • 将所有产品保存到数据库
    • 注意:对我来说,似乎应用服务在这里完成了大部分工作(创建订单、获取产品、更新产品),可以接受吗?
  2. 在订单服务中:

    • 创建一个新订单,插入数据库
    • 生成一个事件 OrderCreated
    • 触发事件处理程序,调用 Product.UpdateQuantity()
    • 注:产品数量不保证立即更新

在现实生活中,哪种方式更受欢迎?在这两种情况下,如何处理产品数量的并发更新?如果数量与用户看到结帐屏幕的时间不同,则通知用户失败?

非常感谢

0 投票
1 回答
376 浏览

entity-framework - 领域事件(Udi 风格)并尝试解决服务层模式

关于 AutoFac、CommonServiceLocator 和 Udi 的域事件 ( http://www.udidahan.com/2009/06/14/domain-events-salvation/ )的有效解决方案,我有一个微妙的问题。我让 Autofac 在 MVC 引导程序中设置 ServiceProvider。但是有两件事让我烦恼:1)域事件是通过使用 CommonServiceLocator 的静态方法引发的。这使得单元测试变得困难,并且它还隐藏了一些我喜欢使用的 Autofac 功能。这导致我... 2)我的事件被 IEventSubsriber 消耗,其中 T 是 DomainEvent。但情况是我喜欢在一个事件上有几个订阅者。这意味着当我提出一个事件时我会得到几个订阅者。

但是我已经通过 AutoFac 用 MetaData 标记了这个订阅者实例:

元数据类是:

所以这个问题。我想实现我可以以某种方式使用抽象工厂(不解决 1)只是将问题转移到另一个地方),AutoFac 委托工厂(Func<> 对泛型不太满意)或者只是一个简单的注入进入 DomainEventDispatcher?

让我感到沮丧的是,我想避免 Domain.Core 程序集中的依赖关系。我知道我今天依赖于 CommonServiceLocator。但是在 Base Entity 类上使用 DI(它会产生什么结果)我不知道有什么简单的方法。我看过 Nicklas Blumhardt 的演示,其中 AutoFac 通过 NHibernate 拦截器将 DomainEventDispatcher 注入实体,并且可以在 Up/Down 期间将事件分派到持久性。整洁的解决方案。但我使用 Entity Framework 5,也希望有一个更简单的解决方案。

期待看到一些答案或至少讨论这个话题。我认为很多人在处理这个问题时都会停下来。也许只是——“好吧,我们只为事件使用 CSL”,它们也为单元测试设定了界限。- “我们跳过事件的单元测试”。这不是问题:)

/最好的问候马格努斯

0 投票
1 回答
105 浏览

c# - 将 IOrderSender 注入域对象

我一直在思考这个问题。一般来说,我尽量避免将服务注入我的域,但我有这种情况:

我有一个 PurchaseOrder 对象。使用某些服务(电子邮件或网络服务)将此订单发送给供应商。订单发送后,应向下订单的用户发送确认信息。

所以我意识到在这种情况下,领域事件将是实现发布 PurchaseOrderMade 事件的好方法。

然后我开始想:

如果订单没有发送,订单是否真的成功了?

您没有因为您决定做并写下来就下订单,而是在您按照合同无误地将其传送给供应商的时间下订单。

所以我重新决定并认为这毕竟可能属于域,所以我应该通过将 IPurchaseOrderSender 注入我的域来发送它,然后在成功交易后发布 OrderMadeEvent 并在 EventHandler 中发送确认。

理由是这样的:

  1. 订单的发送是流程的关键部分,可能会导致状态改变(即设置发送订单的标志)
  2. 确认并不重要,如果失败,订单仍然会进行,一切都会按计划进行。
  3. 它易于阅读,并且可以更改 IOrderService 的实现

问题是:

  1. 这真的有那么糟糕吗?
  2. 它是否违反了 DDD 的原则?
  3. 您以前是否遇到过这种情况并以更好的方式解决了它?

这是代码:

0 投票
2 回答
2153 浏览

c# - 延迟领域事件的创建和分派

我使用域事件模式已经有一段时间了——它使我们能够在域层中封装尽可能多的行为,并为我们应用程序的其他部分订阅域事件提供了一种很好的方式。

目前我们正在使用一个静态类,我们的域对象可以调用它来引发事件:

正如您所看到的,这只不过IEventDispatcher是实际执行调度发布事件的工作的垫片。

我们的调度程序实现只是使用我们的 IoC 容器 (StructureMap) 来定位指定类型事件的事件处理程序。

这在大多数情况下都可以正常工作。但是,这种方法存在一些问题:

仅当实体成功持久化时才应分派事件

参加以下课程:

Order构造函数中,我们提出了一个OrderRaisedEvent. 在我们的应用层中,我们可能会创建订单实例,将其添加到我们的数据库“会话”中,然后提交/保存更改:

这里的问题是在我们成功保存 Order 实体(提交事务)之前引发了域事件。如果保存失败,我们仍然会分派事件。

更好的方法是将事件排队,直到实体被持久化。但是,我不确定如何在维护强类型事件处理程序的同时最好地实现这一点。

在实体被持久化之前不应创建事件

我面临的另一个问题是我们的实体标识符在存储实体(RavenDB - session.Store)之前不会设置/分配。这意味着在上面的示例中,传递给事件的订单标识符实际上是null.

由于我不确定如何实际预先生成 RavenDB 标识符,因此一种解决方案可能是将事件的创建延迟到实际保存实体之前,但我又不是如何最好地实现这一点 - 也许排队集合Func<TEntity, TEvent>

0 投票
1 回答
398 浏览

c# - 通过在领域模型中使用 IoC 来打破“无处不在的语言”?

我的问题是关于Udi对域事件的解决方案,尤其是类DomainEvents(参见下面的代码)

摘自 Udi 的代码。它以静态类的形式存在域模型。

从上面的代码中,静态成员IContainer在域模型中创建了一个 ioc-container-dependency。虽然我不确定 UdiIContainer是接口还是实际的 IoC 容器。

我在他的样本中看不到这样的东西:

我的第一个问题是:课堂上这是IContainer什么DomainEvents如果它真的是一个 IoC 容器,那它不是打破了“在域中没有基础设施”的规则吗?(如果我错了请纠正我)

DDD 的想法不就是将基础设施与域分离吗?

我的第二个问题是:DomainEvents本身是否违反了“DDD 无处不在的语言”的规则?因为它的实现不属于任何领域。

0 投票
2 回答
2243 浏览

cqrs - CQRS - EventListener 可以调用命令吗?

我想在我的项目中使用 CQRS 模式的元素。我想知道我是否正确使用命令和事件。我不确定事件是否可以调用命令。为了更好地展示我想要做什么,我将使用图表和示例。

这是一个例子:

用户调用 TripCreateCommand。TripCreateCommandHandler 完成他的工作并在成功后发布 TripCreatedEvent。

现在我们有两个 TripCreatedEvent 的监听器(监听器执行的顺序无关紧要)

第一个监听器(可以在第二个监听器之后执行):

对于 trip.author.friends 中的每个用户调用两个命令(命令的顺序很重要)

  1. PublishTripOnUserWallCommand
  2. SendNewTripEmailNotificationCommand
  3. 发送NewTripPlatformNotification

第二个监听器(可以在第一个监听器之前执行):

  1. PublishTripOnUserSocials

这是示例图:

在此处输入图像描述

这是一个好方法吗?EventListener 可以调用命令吗,或者我应该以其他方式调用它吗?

0 投票
1 回答
569 浏览

c# - 针对此特定问题的 Autofac 注册技术

我有这堂课:

IEventContainer看起来像这样:

现在IEventContainer在这样的类中使用DomainEvents它:

我的目标是进行DomainEvents.Container注册,以便解决所有处理程序。

在 Autofac 中执行此操作的方法是什么?