问题描述
我是试图理解聚合根概念的众多人之一,我想我已经理解了!
但是,当我开始为这个示例项目建模时,我很快陷入了困境。
I'm one of many trying to understand the concept of aggregate roots, and I think that I've got it!However, when I started modeling this sample project, I quickly ran into a dilemma.
我有两个实体 ProcessType
和 Process
。没有 ProcessType
和 ProcessType
的 Process
是不存在的有许多进程
。因此,进程拥有对类型的引用,没有它就不能存在。
I have the two entities ProcessType
and Process
. A Process
cannot exist without a ProcessType
, and a ProcessType
has many Process
es. So a process holds a reference to a type, and cannot exist without it.
ProcessType
应该是一个集合根?新进程将通过调用 processType.AddProcess(new Process())
创建。
但是,我还有其他实体,它们仅持有对 Process
的引用,并通过 Process.Type $ c访问其类型。 $ c>。在这种情况下,先通过
ProcessType
是没有意义的。
So should ProcessType
be an aggregate root? New processes would be created by calling processType.AddProcess(new Process())
;However, I have other entities that only holds a reference to the Process
, and accesses its type through Process.Type
. In this case it makes no sense going through ProcessType
first.
但是,聚合之外的AFAIK实体仅被允许保存对集合根的引用,而不是对集合内实体的引用。那我这里有两个聚合,每个聚合都有自己的存储库吗?
But AFAIK entities outside the aggregate are only allowed to hold references to the root of the aggregate, and not entities inside the aggregate. So do I have two aggregates here, each with their own repository?
推荐答案
我在很大程度上同意西西弗斯所说的话,特别是关于不将自己限制在DDD的规则上可能会导致非常不合逻辑的解决方案。
I largely agree with what Sisyphus has said, particularly the bit about not constricting yourself to the 'rules' of DDD that may lead to a pretty illogical solution.
关于您的问题,我遇到过很多次这种情况,我将 ProcessType称为查找。查找是定义的对象,并且具有否对其他实体的引用;在DDD术语中,它们是价值对象。我称之为查找的其他示例可能是团队成员的 RoleType,例如可以是测试人员,开发人员或项目经理。甚至将一个人的标题都定义为查找-先生,小姐,夫人,博士
In terms of your problem, I have come across the situation many times, and I would term 'ProcessType' as a lookup. Lookups are objects that 'define', and have no references to other entities; in DDD terminology, they are value objects. Other examples of what I would term a lookup may be a team member's 'RoleType', which could be a tester, developer, project manager for example. Even a person's 'Title' I would define as a lookup - Mr, Miss, Mrs, Dr.
我将您的流程汇总建模为:
I would model your process aggregate as:
public class Process
{
public ProcessType { get; }
}
正如您所说,这些类型的对象通常需要在UI因此需要自己的数据访问机制。但是,我个人并没有为此创建存储库,而是创建了 LookupService。对我来说,这通过严格保留用于聚合根的存储库来保持DDD的优雅。
As you say, these type of objects typically need to populate dropdowns in the UI and therefore need their own data access mechanism. However, I have personally NOT created 'repositories' as such for them, but rather a 'LookupService'. This for me retains the elegance of DDD by keeping 'repositories' strictly for aggregate roots.
以下是我的应用服务器上的命令处理程序以及如何实现的示例此:
Here is an example of a command handler on my app server and how I have implemented this:
团队成员总计:
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填充下拉菜单等:
The client can also make use of the LookupService to populate dropdown's etc:
ILookup<TeamMemberRoleType> roles = _lookupService.GetLookup<TeamMemberRoleType>();
这篇关于简单的汇总根和存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!