创作相关实体的责任

时间:2013-07-01 12:30:26

标签: c# domain-driven-design aggregation

我有一个名为“Task”的实体。对于这个实体,我可以创建多个实体,称为“注释”。我还想要一个名为“CreateComment”的方法。根据Domain Driven Design,如果不创建“Task”类的实例,实体“Comment”就不可能存在。我的问题是:应该放置这个方法:在Task类或Comment类中?它应该像Comment.CreateComment或Task.CreateComment。如果我将此方法放入Task类,那么它是单一责任原则违规吗?

2 个答案:

答案 0 :(得分: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);

好的,正如我之前提到的那样,这个例子在大多数情况下都是过度设计的。但它应该让您了解如何坚持单一责任原则。

答案 1 :(得分:0)

根据GRASP,原则

  

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

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

根据您的描述,听起来至少有3个点是相关的。因此,我会说Task负责创建Comment