【问题标题】:The responsiblity of creation related entities创作相关实体的责任
【发布时间】:2013-06-28 13:54:09
【问题描述】:

我有一个名为“任务”的实体。对于这个实体,我可以创建多个实体,称为“评论”。我还想要一个名为“CreateComment”的方法。根据领域驱动设计,如果不创建“任务”类的实例,实体“评论”就不能存在。我的问题是:这个方法应该放在哪里:在 Task 类中还是在 Comment 类中?它应该像 Comment.CreateComment 还是 Task.CreateComment。如果我把这个方法放到Task类中,会不会违反单一职责原则?

【问题讨论】:

    标签: c# domain-driven-design aggregation


    【解决方案1】:

    我认为该方法应该在Task 实体上。但话虽如此,该方法不应该是Create,而是Add,因为我不认为Task 对象有责任创建评论。相反,我会使用这样的东西,这有点矫枉过正,但主要是因为我喜欢进度流畅的界面和对象构建器模式:)

    任务类,一目了然

    public class Task
    {
        private readonly IList<Comment> Comments = new List<Comment>();
    
        public void AddComment(ICommentBuilderFinalization commentBuilder)
        {
            Comments.Add(commentBuilder.MakeComment());
        }
    }
    

    评论类,再一次非常自我解释

    public class Comment
    {
        public string Text { get; set; }
        public string PostedBy { get; set; }
        public DateTime PostedAt { get; set; }
    }
    

    对象构建器和渐进式流畅界面

    // First progressive interface
    public interface ICommentBuilder
    {
        ICommentBuilderPostBy PostWasMadeNow();
        ICommentBuilderPostBy PostWasMadeSpecificallyAt(DateTime postedAt);
    }
    
    // Second progressive interface
    public interface ICommentBuilderPostBy
    {
        ICommentBuilderPostMessage By(string postedBy);
    }
    
    // Third progressive interfacve
    public interface ICommentBuilderPostMessage
    {
        ICommentBuilderFinalization About(string message);
    }
    
    // Final
    public interface ICommentBuilderFinalization
    {
        Comment MakeComment();
    }
    
    // implementation of the various interfaces
    public class CommentBuilder : ICommentBuilder, ICommentBuilderPostBy, ICommentBuilderPostMessage, ICommentBuilderFinalization
    {
        private Comment InnerComment = new Comment();
    
        public Comment MakeComment()
        {
            return InnerComment;
        }
    
        public ICommentBuilderFinalization About(string message)
        {
            InnerComment.Text = message;
            return this;
        }
    
        public ICommentBuilderPostMessage By(string postedBy)
        {
            InnerComment.PostedBy = postedBy;
            return this;
        }
    
        public ICommentBuilderPostBy PostWasMadeNow()
        {
            InnerComment.PostedAt = DateTime.Now;
            return this;
        }
    
        public ICommentBuilderPostBy PostWasMadeSpecificallyAt(DateTime postedAt)
        {
            InnerComment.PostedAt = postedAt;
            return this;
        }
    }
    

    把它们放在一起

    var task = new Task();
    var commentBuilder = new CommentBuilder().PostWasMadeNow().By("Some User").About("Some Comment");
    
    task.AddComment(commentBuilder);
    

    好的,正如我之前提到的,这个例子在大多数情况下都被过度设计了。但它应该让您了解如何才能忠于单一职责原则。

    【讨论】:

    • “用更少的东西做更多的事情是徒劳的” - 奥卡姆的威廉。
    【解决方案2】:

    根据GRASP,原则

    如果以下一项或多项适用,则 B 类应负责创建 A 类的实例:

    • B 的实例包含或复合聚合了 A 的实例
    • B 的实例记录 A 的实例
    • B 的实例密切使用 A 的实例
    • B 的实例具有 A 实例的初始化信息并在创建时传递它。

    从您的描述看来,其中至少有 3 点是相关的。因此我会说Task负责创建Comment

    【讨论】:

      猜你喜欢
      • 2012-02-28
      • 2020-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-09
      相关资源
      最近更新 更多