【问题标题】:How to represent references in DDD entites如何在 DDD 实体中表示引用
【发布时间】:2011-09-16 05:20:08
【问题描述】:

我正在尝试掌握 DDD,并觉得我已经很好地掌握了实体、聚合、聚合根、存储库和值对象以及如何在代码中实际表示这些概念。

我仍在苦苦挣扎的是如何在实际代码中表示引用(即不构成聚合的关系)。假设我有以下两个聚合

DISCUSSIONGROUP (entity, aggregate root)
 +name: string
 +ENTRY (entity)
   +title: string
   +message: string
   +timestamp: date
   +madeByUser: USER

USER (entity, aggregate root)
 +name: string
 +email: string
 +memberOf: DISCUSSIONGROUP

用户可以是讨论组的成员,但用户实体不属于同一聚合。然而,两者之间仍然存在关系(参考)。在查看实际代码时,我会实现聚合关系,例如(使用 C#):

interface IDiscussionGroup {
    string Name { get; }
    IList<IEntry> { get; }
    ...
}

即使用简单的 C# 引用。您是否会以相同的方式实现 DDD 引用(如上所述),即:

interface IUser {
    IDiscussionGroup MemberOf { get; }
    ...
}

是否应该使用其他构造来指示较弱的关系类型?

【问题讨论】:

    标签: c# domain-driven-design


    【解决方案1】:

    这真的取决于您的要求。没有一种方法可以做得很好,但我要做的是将 DISCUSSIONGROUP 实体中的 madeByUser 属性设为 ValueObject。

    为什么?因为当显示来自 DisscusionGroup 的条目时,我对要在条目上显示的用户的名称和电子邮件很感兴趣。我不希望该用户在从数据库中删除时消失在我的条目中。如果 User 实体有更多的属性和行为,例如在显示用户信息时我对此不感兴趣,因此 ValueObject 会很好。此外,您可以在多个条目之间共享该 VO,而无需为每个条目检索具体用户的实例。

    另一方面,用户聚合是否与讨论组在相同的上下文中使用?我的意思是 DiscussionGroup 可以是一个上下文中的实体(例如在前台用例中)和用户管理后台中的值对象(我们对管理讨论组不感兴趣,而只对用户感兴趣,所以一个简单的有关讨论组的信息就足够了)。但是,您可能希望从 DiscussionGroup 实体到 User 实体的引用,或者在这种情况下也将 DiscussionGroup 设为 VO。您是否需要检索给定用户的所有讨论组和条目?或者您只需要一些可以嵌入到值对象中的信息?

    很抱歉,如果我没有很好地回答您的问题,但是直接引用或只是在聚合之间使用某种共享 ID 或使用 VO 确实取决于用例和 行为 你必须执行。

    如果我可以在不进行延迟加载和其他类似操作的情况下检索聚合中的所有数据,我个人会检查我是否定义了一个好的聚合边界。

    也许其他人有不同的观点。

    【讨论】:

    • 使用值对象是有意义的。但是,假设我想从用户所做的每个讨论条目中创建一个指向用户个人资料的链接。一个好的方法是将用户的 id 包含在 VO 中以便能够创建该链接吗?
    • 我会那样做。您必须在某一时刻建立关系,但这种关系可能是聚合之间的弱“id”。
    【解决方案2】:

    “持有某物”和“属于某物”看起来很相似。

    不同之处在于 - 何时构造。

    public class User{
      public IList<DiscussionGroup> GroupMembership{get; private set;}
      public User(){
        GroupMembership=new List<DiscussionGroup>();
      }
      public void JoinGroup(DiscussionGroup group){
        GroupMembership.Add(group);
      }
      public bool IsMemberOf(DiscussionGroup group){
        return GroupMembership.Contains(group);
      }
      public void EnsureMembership(DiscussionGroup group){
        ThrowIf(!IsMemberOf(this),
          "User is not a member of this discussion group");
      }
    }
    public class DiscussionGroup{
      public IList<Discussion> Discussions {get;private set;}
      public DiscussionGroup(){
        Discussions=new List<Discussion>();
      }
      public Discussion CreateDiscussion(string name, Post firstPost){
        CurrentUser.EnsureMembership(this);
        var discussion=new Discussion(this, name, firstPost);
        Discussions.Add(discussion);
        return discussion;
      }
    }
    public class Discussion{
      public DiscussionGroup Group{get; private set;}
      public Discussion(DiscussionGroup group, string name, Post firstPost){
        CurrentUser.EnsureMembership(group);
        Guard.Null(group);
        Group=group;
        Name=name;
        Posts=new List<Post>{firstPost};
      }
      public void WritePost(string text){
        CurrentUser.EnsureMembership(group);
        Posts.Add(new Post(this,text));
      }
    }
    public class Post{
      public Discussion Discussion{get; private set;}
      public string Text {get; private set;}
      public Post(Discussion discussion, string text){
        Guard.Null(discussion);
        Discussion=discussion;
        Text=text;
      }
    }
    
    //usage
    var me=new User();
    var you=new User();
    var stackOverflow=new DiscussionGroup();
    me.JoinGroup(stackOverflow);
    you.JoinGroup(stackOverflow);
    
    LoginAs(you);
    var question="I'm trying to get a handle on DDD and feel that...";
    var discussion=stackOverflow.CreateDiscussion
      ("How to represent references in DDD entites",question);
    
    LoginAs(me);
    var answer="'Holds something' and 'belongs to something'...";
    discussion.WritePost(answer);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-24
      • 1970-01-01
      • 2012-07-30
      • 1970-01-01
      相关资源
      最近更新 更多