简单的聚合根和存储库

时间:2011-02-07 13:34:00

标签: domain-driven-design repository aggregate

我是众多试图理解聚合根的概念之一,我认为我已经掌握了它! 但是,当我开始对这个示例项目进行建模时,我很快陷入了两难境地。

我有两个实体ProcessTypeProcess。没有ProcessProcessType不能存在,而ProcessTypeProcessProcessType。因此,一个进程持有一个类型的引用,没有它就不能存在。

那么processType.AddProcess(new Process())应该是聚合根吗?通过调用Process创建新流程; 但是,我有其他实体只保留对Process.Type的引用,并通过ProcessType访问其类型。在这种情况下,首先通过{{1}}是没有意义的。

但聚合之外的AFAIK实体只允许保留对聚合根的引用,而不允许聚合内部的实体。那么我在这里有两个聚合,每个聚合都有自己的存储库吗?

3 个答案:

答案 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个。