通过聚合根更新聚合的最正确方法是什么?
What is the most correct method of updating an Aggregate through an Aggregate Root?
遵循 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!");
};
}
}
如果User
是聚合的根,那么对聚合的所有修改都应该通过调用根上的方法来进行;所以你的 "Method 1" 是正确的模式。
具体来说 -- 访问聚合中的其他实体是通过调用根上的方法来实现的,并允许根在必要时将工作委托给内部实体。
关键是聚合根定义了域模型和应用程序之间的边界。
现在,在某些情况下,这种限制似乎没有多大意义。当这种情况发生时,挑战你的假设:你确定电子邮件是一个实体吗?您确定该实体需要与用户实体在事务上保持一致吗?
对于电子邮件地址之类的东西,我希望电子邮件地址将成为一个值对象,可以将其添加到用户内部的集合中。所以我不希望将 EmailId 视为抽象。
user.FixTypoInEmailAddress("updated@email.com", "updated1@email.com")
Do not multiply entities beyond necessity.
遵循 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!");
};
}
}
如果User
是聚合的根,那么对聚合的所有修改都应该通过调用根上的方法来进行;所以你的 "Method 1" 是正确的模式。
具体来说 -- 访问聚合中的其他实体是通过调用根上的方法来实现的,并允许根在必要时将工作委托给内部实体。
关键是聚合根定义了域模型和应用程序之间的边界。
现在,在某些情况下,这种限制似乎没有多大意义。当这种情况发生时,挑战你的假设:你确定电子邮件是一个实体吗?您确定该实体需要与用户实体在事务上保持一致吗?
对于电子邮件地址之类的东西,我希望电子邮件地址将成为一个值对象,可以将其添加到用户内部的集合中。所以我不希望将 EmailId 视为抽象。
user.FixTypoInEmailAddress("updated@email.com", "updated1@email.com")
Do not multiply entities beyond necessity.