首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是领域事件的真实世界,生产级案例(理解为同一有限上下文和过程中的事件)?

什么是领域事件的真实世界,生产级案例(理解为同一有限上下文和过程中的事件)?
EN

Stack Overflow用户
提问于 2021-10-12 00:37:40
回答 1查看 43关注 0票数 0

如果我们有一个有限制的上下文,比如aggregate1发布event1aggregate2想要对其作出反应的2个聚合,那么我们有1种方法:

  1. in process event1 > aggregate2响应它,
  2. event1发布到消息总线,并让一些单独的进程将其捡起&调用aggregate2方法(S)

G 212

无论是在同一个有界的上下文中,如果我们想确保不丢失event1 ( aggregate1之间的应用程序崩溃被保存,而aggregate2是为了响应event1而保存的,例如)我很难找到一个例子,说明什么时候选项1会比选项2更好(超过可能的验证)?

我一定是遗漏了什么,但在我所知的这一点上,这似乎是一个纯粹的理论概念,在我看来,在可靠性和保持正确状态的能力方面,这似乎是一个没有现实世界价值的概念。

当然,发布一条消息并让单独的进程侦听/响应它似乎有点过火了,但是在某个地方没有持久化的域事件有什么实际用途(即使在本地DB中也是如此,在这种情况下,我称之为原始消息总线)?

我遗漏了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-12 13:30:38

,在有界的上下文和进程中,什么是领域事件的真实应用?

需求:

可以创建categories.

  • Category名称的
  • 用户必须是唯一的。
  • 用户可以重命名类别。

(类别将具有许多与命名无关的其他属性)。

DDD概念:

类别聚合应该负责它自己的内部不变量,但不能知道其他类别聚合的详细信息。

如何确保当前类别的类别名称是全局唯一的,而不需要类别访问所有其他类别?

答:域事件

DomainEvent

代码语言:javascript
复制
public CategoryRenamed : DomainEvent
{
    public Category Category { get; }

    internal CategoryRenamed(Category category)
    {
        this.Category = category;
    }
}

DomainEventHandler

代码语言:javascript
复制
public CategoryRenamedHandler : IDomainEventHandler<CategoryRenamed>
{
    public CategoryRenamedHandler(CategoryRenamed domainEvent)
    {
        string proposedName = domainEvent.Category.Name;

        // query database to ensure that proposedName is not already in use
        if (inUse)
            throw new Exception($"Name {proposedName} already in use." ;
    }
}

实体

代码语言:javascript
复制
public abstract class Entity
{
    List<DomainEvent> _domainEvents = new List<DomainEvent>();

    protected AddDomainEvent(DomainEvent domainEvent)
    {
        _domainEvents.Add(domainEvent);
    }

    public List<DomainEvent> DomainEvents => _domainEvents;
}

范畴

代码语言:javascript
复制
public class Category : Entity
{
    public Guid Id { get; private set; }
    public string Name { get; private set; }

    public Category(Guid id, string name)
    {
        Id = id;
        SetName(name);
    }

    public Rename(string name)
    {
        SetName(name);
    }

    void SetName(string name)
    {
        // Local Invariants
        if (string.IsNullOrWhitespace(name))
            throw new Exception("Invalid name");

        Name = name;

        // Add a domain event for the infrastructure to process
        AddDomainEvent(new CategoryRenamed(this));
    }
}

命令

代码语言:javascript
复制
public class AddCategoryCommand
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

CommandHandler

代码语言:javascript
复制
public class CommandHandler : ICommandHandler<AddCategoryCommand>
{
    readonly ICategoryRepository _categoryRepository;

    public CommandHandler(ICategoryRepository categoryRepository)
    {
        _categoryRepository = categoryRepository;
    }

    public void HandleCommand(AndCategoryCommand command)
    {
        Category newCategory = new(command.Id, command.Name);

        // Check for domain events before committing to repository
        DomainEventDispatcher.DispatchEvents(newCategory.DomainEvents);
        // Dispatcher will find the CategoryRenamed event and send 'in-process'
        // to CategoryRenamedHandler
        // If name was is in use an error will be thrown by the handler (see above)

        _categoryRepository.Add(newCategory);
    }
}

结局

您的分类聚合已经强制执行了它自己的本地不变量,域命令和domainevent处理基础结构已经被利用,以确保所有类别的名称的唯一性。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69533841

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档