DDD - 聚合根和创建行为对象

7 domain-driven-design

我想问一些关于如何避免编写仅仅是数据容器的对象的建议.

请考虑以下聚合根:

public class Post : IAggregateRoot
{
  List<Comment> Comments {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

鉴于控制聚合根如何工作的原则,调用上面这样的代码是否有效?

new Post().Comments.Add(New Comment("stuff"));
Run Code Online (Sandbox Code Playgroud)

或者这是正确的方法吗?

public class Post : IAggregateRoot
{
      List<Comment> Comments {get; private set;}
      public void AddComment(string message)
      {
        Comments.Add(new Comment(message)); 
      }
}
Run Code Online (Sandbox Code Playgroud)

并且这样称呼:

new Post().AddComment("stuff");
Run Code Online (Sandbox Code Playgroud)

这是Eric Evan意味着Aggregate Roots是原子的吗?

如果是这种情况,是否意味着实体没有任何公共设置者,而是具有支持方法(AddThis,RemoveThat)?这是你如何创建具有丰富行为的对象?

Vij*_*tel 5

你已经有了聚合根的概念,但你的两个选择实际上是关于实现 - 两者都是有效的.

选项1

  • 优点:您的实体界面仍然非常干净.

  • 缺点:该Add方法需要逻辑来连接Post和之间的关系 Comment(想想NHibernate).您可以创建强类型集合并覆盖Add方法,也可以将事件提升回Post处理.

选项2

  • 优点:这些Add/Remove方法为布线逻辑提供了方便的位置.

  • 缺点:随着集合属性数量的增加,您可能会遇到大量Add/Remove方法.此外,公开的集合必须是ReadOnly,以确保Comments始终使用特殊方法添加/删除.

我的偏好是选项1 - 我使用引发事件的泛型集合.恕我直言,感觉更自然,其他开发人员更容易编码.虽然SO上的其他人表示不同意.

当我们谈论行为时,我们谈论的是将逻辑附加到实体.例如.如果您想Comments在5天后停止添加,您会询问Post添加a Comment是否有效,并且Post包含进行检查的逻辑.