ddv*_*ddv 7 domain-driven-design aggregateroot
我有一个用户在表单中回答问题的系统.我有代表这个模型的对象,但我不太确定如何根据DDD组织这些对象.
每个对象都有超过15个属性,如果没有父对象,每个属性都没有意义.根据DDD,我认为Form实体应该是Aggregate Root,所有其他对象应该是值对象.这意味着我只需要一个表单实体的存储库.在这种情况下,FormRepository将与子对象的各种CRUD方法混杂在一起.我的推理是否适合DDD?我最终得到了一个非常广泛的聚合物吗?我相信这样的表示很容易导致性能问题.
是的,DDD中的深层次结构很好.
我最终得到了一个非常广泛的聚合物吗? - 如果现实情况复杂,并且您的领域模型尽可能最好,那么最终会得到一个复杂的聚合根.
是的,Form应该是聚合根.
所有其他对象应该是值对象 - 错误,所有其他对象应该是非聚合根实体(带有Id),而没有用于获取它们的存储库.值对象没有Id,值对象的相等性仅由其属性值决定,而不是由Ids相等(此处有更多信息).
在这种情况下,FormRepository会混杂使用各种子对象的CRUD方法 - 不,存储库应该只包含有关聚合根的方法,即Get<T> , Save<T> where T : IAggregateRoot,一旦获得聚合根的实例,就可以遍历属性和方法来获取你需要什么.例:
var formId = 23;
var form = _formRepository.Get(formId);
var firstGroup = form.Sections.First().Group().First();
Run Code Online (Sandbox Code Playgroud)
或更好
var groupIndex = 1;
var firstGroup = form.GetGroupAt(groupIndex);
Run Code Online (Sandbox Code Playgroud)
哪里
public Group GetGroupAt(int groupIndex)
{
Sections.First().Group().ElementAt(groupIndex);
}
Run Code Online (Sandbox Code Playgroud)
我相信这样的表示很容易导致性能问题 - 如果你使用CQRS,你Form将从命令处理程序调用一些域方法,如果你使用NHibernate实现持久性,它将默认使用延迟加载,并且只会Form从DB 加载,然后它只加载你真正触摸的实体,所以例如Sections.First()从DB加载所有部分,但不加载组和其余部分.对于查询,您将创建一个FormDto(数据传输对象)和其他可能被展平的dtos来获取所需形式的数据(可能与您的实体结构不同,UI可能会驱动dto结构).有关DDD/CQRS/NHibernate/Repository的信息,请查看我的博客
即使答案已被接受,我想我也可以加上我的2美分:
深层次结构(可能)很好,但请记住聚合背后的想法是实际上阻止这种情况.我倾向于将实体集中在以下方面:
"这个实体是否有任何意义,而不该AR?"
由于我的模型没有任何上下文,我将使用Order/ OrderLine.没有这个OrderLine有什么意义Order吗?我可以单独使用订单行做任何事情(行为)吗?这里显而易见的答案是"不".
每个模型都需要根据上下文进行处理.但所有权并不一定意味着遏制.
当你使用单独的有界上下文时,这些可能更容易看到,前提是一个BCs正确:)
在你的情况下,Answer没有它可能没有意义Question.但也许一个人Question可以住在QuestionBank卑诗省,一个特定的问题可能会用在ExaminationBC和你的Enrollment卑诗省.所有这些都是完全弥补的,这取决于你的背景.
因此,如果是一个Question可以成为AR 的案例,那么您的FormAR 所拥有的问题可能只是一个价值对象,甚至是一个简单的QuestionId.