【问题标题】:What is the most correct method of updating an Aggregate through an Aggregate Root?通过聚合根更新聚合的最正确方法是什么?
【发布时间】:2017-12-12 18:20:59
【问题描述】:

遵循 DDD、Aggregate 和 Aggregate Root 的良好实践。我有以下情况:

  • User(聚合根)
  • UserEmail 的集合(在User 内)

假设我已经为用户注册了 10 封电子邮件,那么更新其中一封电子邮件的最正确和最有效的方法是什么?

方法一

static void UpdateEmailForExistingUserMethod1()
{
    var userId = new Guid("f0cd6e3e-b95b-4dab-bb0b-7e6c6e1b0855");
    var emailId = new Guid("804aff75-8e48-4f53-b55d-8d3ca76a2df9");

    using(var repository = new UserRepository())
    {
        // I'm going to return the user with all their emails?
        // I will not have performance problems for bringing all emails from this user?
        var user = repository.GetUserById(userId);

        if (user == null)
        {
            Console.WriteLine("User not found");
            return;
        }

        // Updating Email in Aggregate Root
        user.UpdateEmail(emailId, "updated1@email.com");

        // Commit in repository
        if (repository.Commit() > 0)
        {
            Console.WriteLine("E-mail updated with method 1!");
        };
    }
}

方法二:

static void UpdateEmailForExistingUserMethod2()
{
    var usuarioId = new Guid("f0cd6e3e-b95b-4dab-bb0b-7e6c6e1b0855");
    var emailId = new Guid("3b9c2f36-659e-41e8-a1c6-d879ab58352c");

    using(var usuarioRepository = new UserRepository())
    {
        if (!usuarioRepository.UserExists(usuarioId))
        {
            Console.WriteLine("User not found");
            return;
        }

        if (!usuarioRepository.EmailExists(emailId))
        {
            Console.WriteLine("E-mail not found");
            return;
        }

        // Grab only the email that I will update from the repository, 
        // optimizing performance
        var usuarioEmail = usuarioRepository.GetEmailById(emailId);

        // Updates the e-mail through a method of the e-mail entity itself
        usuarioEmail.Update("updated2@email.com");

        // Commit in repository
        if (usuarioRepository.Commit() > 0)
        {
            Console.WriteLine("E-mail updated with method 2!");
        };
    }
}

【问题讨论】:

    标签: domain-driven-design aggregate aggregateroot


    【解决方案1】:

    如果User 是聚合的根,那么对聚合的所有修改都应该通过调用根上的方法来进行;所以你的“方法1”是正确的模式。

    具体来说——对聚合中其他实体的访问是通过调用根上的方法来实现的,并允许根在必要时将工作委托给内部实体。

    关键是聚合根定义了域模型和应用程序之间的边界。

    现在,在某些情况下,这种约束似乎没有多大意义。当这种情况发生时,挑战你的假设:你确定电子邮件是一个实体吗?您确定该实体需要在事务上与用户实体保持一致吗?

    对于电子邮件地址之类的东西,我希望电子邮件地址将是一个值对象,可以将其添加到用户内部的集合中。所以我不希望将 EmailId 视为抽象。

    user.FixTypoInEmailAddress("updated@email.com", "updated1@email.com")
    

    不要增加不必要的实体。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-10
      相关资源
      最近更新 更多