Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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.

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.

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. This would make it easier e.g. 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

like image 900
Chris Avatar asked Jan 28 '10 15:01

Chris


People also ask

What is considered Domain-Driven Design pattern?

Domain-Driven Design(DDD) is a collection of principles and patterns that help developers craft elegant object systems. Properly applied it can lead to software abstractions called domain models. These models encapsulate complex business logic, closing the gap between business reality and code.

What is DDD example?

An aggregate is a domain-driven design pattern. It's a cluster of domain objects (e.g. entity, value object), treated as one single unit. A car is a good example. It consists of wheels, lights and an engine.

What is tactical design DDD?

Tactical DDD is when you define your domain models with more precision. The tactical patterns are applied within a single bounded context. In a microservices architecture, we are particularly interested in the entity and aggregate patterns.

What is Domain-Driven Design simple explanation?

Domain-driven design (DDD) is a software development philosophy centered around the domain, or sphere of knowledge, of those that use it. The approach enables the development of software that is focused on the complex requirements of those that need it and doesn't waste effort on anything unneeded.


1 Answers

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. Furthermore the Parent property on the Child class should be read only. 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;
    } 
} 
like image 139
Klaus Byskov Pedersen Avatar answered Oct 07 '22 18:10

Klaus Byskov Pedersen