我是众多试图理解聚合根的概念之一,我认为我已经掌握了它!
但是,当我开始对这个示例项目进行建模时,我很快陷入了两难境地.
但是,当我开始对这个示例项目进行建模时,我很快陷入了两难境地.
我有两个实体ProcessType和Process.没有ProcessType,Process不能存在,ProcessType有很多进程.所以一个进程持有一个类型的引用,没有它就不能存在.
ProcessType应该是聚合根吗?通过调用processType.AddProcess(new Process())创建新进程;
但是,我有其他实体只保存对Process的引用,并通过Process.Type访问其类型.在这种情况下,首先通过ProcessType是没有意义的.
但聚合之外的AFAIK实体仅允许保留对聚合根的引用,而不允许对聚合内的实体进行引用.那么这里有两个聚合,每个聚合都有自己的存储库吗?
解决方法
我基本上同意西西弗斯所说的话,特别是关于不要将自己限制在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>();