我是众多试图理解聚合根的概念之一,我认为我已经掌握了它! 但是,当我开始对这个示例项目进行建模时,我很快陷入了两难境地。
我有两个实体ProcessType
和Process
。没有Process
,ProcessType
不能存在,而ProcessType
有Process
个ProcessType
。因此,一个进程持有一个类型的引用,没有它就不能存在。
那么processType.AddProcess(new Process())
应该是聚合根吗?通过调用Process
创建新流程;
但是,我有其他实体只保留对Process.Type
的引用,并通过ProcessType
访问其类型。在这种情况下,首先通过{{1}}是没有意义的。
但聚合之外的AFAIK实体只允许保留对聚合根的引用,而不允许聚合内部的实体。那么我在这里有两个聚合,每个聚合都有自己的存储库吗?
答案 0 :(得分:14)
我基本同意西西弗所说的话,特别是关于不要将自己限制在DDD的“规则”中,这可能导致一个非常不合逻辑的解决方案。
就你的问题而言,我多次遇到过这种情况,我将'ProcessType'称为查找。查找是“定义”的对象,并且对其他实体具有无引用;在DDD术语中,它们是值对象。我所说的查找的其他示例可以是团队成员的“RoleType”,例如,可以是测试人员,开发人员,项目经理。即使是一个人的'标题',我也会将其定义为查找 - 先生,小姐,夫人,博士
我会将您的流程聚合建模为:
public class Process
{
public ProcessType { get; }
}
正如您所说,这些类型的对象通常需要填充UI中的下拉列表,因此需要自己的数据访问机制。但是,我个人并没有为他们创建“存储库”,而是“LookupService”。这对我来说保留了DDD的优雅,通过严格保持“存储库”的聚合根源。
以下是我的应用服务器上的命令处理程序示例以及我如何实现它:
团队成员聚合:
public class TeamMember : Person
{
public Guid TeamMemberID
{
get { return _teamMemberID; }
}
public TeamMemberRoleType RoleType
{
get { return _roleType; }
}
public IEnumerable<AvailabilityPeriod> Availability
{
get { return _availability.AsReadOnly(); }
}
}
命令处理程序:
public void CreateTeamMember(CreateTeamMemberCommand command)
{
TeamMemberRoleType role = _lookupService.GetLookupItem<TeamMemberRoleType>(command.RoleTypeID);
TeamMember member = TeamMemberFactory.CreateTeamMember(command.TeamMemberID,
role,
command.DateOfBirth,
command.FirstName,
command.Surname);
using (IUnitOfWork unitOfWork = UnitOfWorkFactory.CreateUnitOfWork())
_teamMemberRepository.Save(member);
}
客户端也可以使用LookupService来填充下拉列表等:
ILookup<TeamMemberRoleType> roles = _lookupService.GetLookup<TeamMemberRoleType>();
答案 1 :(得分:10)
答案 2 :(得分:0)
看,我认为你必须重组你的模型。使用ProcessType,如Value Object和Process Agg Root。 这样每个进程都有一个processType
Public class Process
{
Public Process()
{
}
public ProcessType { get; }
}
为此你只需要1个根而不是2个。