简体   繁体   English

域驱动设计 - 父子关系模式 - 规范模式

[英]Domain Driven Design - Parent child relation pattern - Specification pattern

I was wondering which of the following is considered to be a best practice when dealing with parent child relationships. 我想知道在处理父母子女关系时,以下哪项被认为是最佳做法。

1) The following example seems to be a common practice, but when creating an instance of a child, it will be in an invalid state as long as it is not added to the parent. 1)以下示例似乎是一种常见做法,但在创建子实例时,只要未添加到父级,它就处于无效状态。 Couldn't this lead to problems regarding validation etc. 这不会导致验证等问题。

public class Parent
{
    private ICollection<Child> children;

    public ReadOnlyCollection Children { get; }

    public void AddChild(Child child)
    {
        child.Parent = this;
        children.Add(child);
    }
}


public class Child
{
    internal Parent Parent
    {
        get;
        set;
    }

    public Child()
    {
    }
}

2) The next sample would take care that a child must always be related to its parent. 2)下一个样本将注意孩子必须始终与其父母相关。

public class Parent
{
    private ICollection<Child> children;

    public ReadOnlyCollection Children { get; }

    public Child CreateChild()
    {
        var child = new Child();
        child.Parent = this;
        children.Add(child);
        return child;
    }
}


public class Child
{
    internal Parent Parent
    {
        get;
        set;
    }

    internal Child()
    {
    }
}

3) In the last example that child takes care of the relation to its parent itself. 3)在最后一个例子中,孩子负责与父母本身的关系。

public class Parent
{
    private ICollection<Child> children;

    public ReadOnlyCollection Children { get; }

    public void AddChild(Child child)
    {
        child.Parent = this;
        children.Add(child);
    }
}


public class Child
{
    public Parent Parent
    {
        get;
        set;
    }

    public Child(Parent parent)
    {
        this.Parent = parent;
    }
}

Which pattern is considered the best? 哪种模式被认为是最好的? I believe that pattern 2 might be the best since then a child can never exist without a relation to its parent. 我相信模式2可能是最好的,因为如果没有与父母的关系,孩子就永远不会存在。 This would make it easier eg when implementing a specification pattern that might do things like: 这将使得例如在实现可能执行以下操作的规范模式时更容易:

public class ChildSpecification
{
    bool IsSatisfiedBy(Child child)
    {
        return child.Parent.Children.Where(someCondition).Count > 0;
    }
}

The above specification can only work if a child has a parent. 上述规范只有在孩子有父母的情况下才有效。

What do you think? 你怎么看? Do you know better ways? 你知道更好的方法吗? Thanks in advance 提前致谢

I definitely like suggestion number 2, but I think that it misses something important that is found in 3, namely that if a Child object cannot exist without a Parent it should take a Parent object in its constructor. 我非常喜欢建议2,但我认为它错过了3中发现的重要内容,即如果没有Parent就不能存在Child对象,那么它应该在其构造函数中使用Parent对象。 Furthermore the Parent property on the Child class should be read only. 此外, Child类的Parent属性应该是只读的。 So you would end up with something like: 所以你最终会得到类似的东西:

public class Parent 
{ 
    private ICollection<Child> children; 

    public ReadOnlyCollection Children { get; } 

    public Child CreateChild() 
    { 
        var child = new Child(this); 
        children.Add(child); 
        return child; 
    } 
} 


public class Child 
{ 
    internal Parent Parent 
    { 
       get; 
       private set; 
    } 

    internal Child(Parent parent) 
    { 
       this.Parent = parent;
    } 
} 

Since I've just encountered the same design desissions and question still not marked as answered I'll post my vision on solution of this problem - maybe it'll help anyone. 由于我刚刚遇到了相同的设计缺陷和问题仍未标记为已回答,我将发布我对解决此问题的看法 - 也许它会帮助任何人。 This solution actually perfectly viable for use with NHibernate. 这个解决方案实际上非常适合与NHibernate一起使用。

public class Parent
{
    private readonly ISet<Child> _children = new HashedSet<Child> ();
    public virtual IEnumerable<Child> Children { get { return new ImmutableSet<Child> (this._children); }  }


    protected internal virtual void AddChild (Child child)
    {
        this._children.Add(child);
    }
}


public class Child
{
    public virtual Parent Parent { get; protected set; }


    protected Child()
    {
    }


    public static Create (Parent parent)
    {
        if (parent == null)
            throw new ArgumentNullException ("parent");

        var child = new Child
        {
            Parent = parent
        };

        child.Parent.AddChild (child);

        return child;
    }
}

That's differs from your #2 option in a way that creation of the child object (and invalidating it's initial values) are gathered withing child object itself and not in parent object as you suggested in #2. 这与您的#2选项的不同之处在于,创建子对象(并使其初始值无效)是使用子对象本身而不是在#2中建议的父对象中收集的。

Tho one thing I'm not sure if it's considered bad design or not if we create child objects with personal factory method ( Child.Create ). 如果我们用个人工厂方法( Child.Create )创建子对象,那么我不确定它是否被认为是糟糕的设计。

I hope someone with more experience in using DDD could comment on that. 我希望有更多使用DDD经验的人可以对此发表评论。

I tend to use option (1) - has always worked well for me. 我倾向于使用选项(1) - 对我来说一直很好。 The important thing is not to expose the children collection itself to the outside world - the Parent should be able to mediate all the access. 重要的是不要将子集合本身暴露给外界 - 父母应该能够调解所有访问权限。 But I'm perfectly happy for a Child to be created elsewhere - I only care about it when it gets added to the Parent, and at this point it can be checked for validity etc. etc. 但我很高兴在其他地方创建一个孩子 - 我只关心它,当它被添加到父母,并在这一点上,它可以检查有效性等。

I don't understand your specification example: it seems like your ChildSpecification would return true if any of the parent's children has someCondition as true. 我不明白你的规范示例:如果父母的任何一个孩子的someCondition为true,看起来你的ChildSpecification会返回true。 Surely IsSatisfiedBy(Child child) should only return true if the specific child passed as a parameter satisfied the condition. 肯定IsSatisfiedBy(Child child)只有在特定子项作为参数满足条件时才返回true。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM