title: Proper DDD way to create and remove child in oneToMany relation?
body: <p>I am struggling to find the proper DDD way to have a parent/child oneToMany relationship that:</p>
  
  <ul>
  <li>Ensures entities cannot exist in invalid state</li>
  <li>Exposes no unwanted methods (i.e. a clean API)</li>
  </ul>
  
  <p>I am using PHP and Doctrine2 but I guess this applies to many other languages/platforms as well. Here's my base entity code. I have <code>Parent</code> and <code>Child</code> objects. A <code>Child</code> cannot exist without a parent.</p>
  
  <pre><code>/**
   * @ORM\Entity
   */
  class ParentClass
  {
      /**
       * @ORM\OneToMany(targetEntity="Child", mappedBy="parent", orphanRemoval=true, cascade={"persist", "remove"})
       */
      private $children;
  }
  
  /**
   * @ORM\Entity
   */
  class Child
  {
      /**
       * @ORM\ManyToOne(targetEntity="Base", inversedBy="children")
       * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE", nullable=false)
       */
      private $parent;
  }
  </code></pre>
  
  <p>But how should I create and remove child entities?</p>
  
  <p>To enfore consistency I could have the parent as a constructor parameter for Child:</p>
  
  <pre><code>class ParentClass
  {
      public function addChild(Child $child)
      {
          $this-&gt;children[] = $child;
      }
  
      public function removeChild(Child $child)
      {
          $this-&gt;children-&gt;removeElement($child);
      }
  }
  
  class Child
  {
      public function __construct(ParentClass $parent)
      {
          $this-&gt;parent = $parent;
          $this-&gt;parent-&gt;addChild($this);
      }
  }
  
  $parent = new ParentClass();
  $child = new Child($parent);
  </code></pre>
  
  <p>The problem with this is that it exposes addChild which really shouldn't be used by developers now. It would need a whole load of extra checks to ensure you cannot move children between parents.</p>
  
  <p>As an alternative I could use a setter:</p>
  
  <pre><code>class ParentClass
  {
      public function addChild(Child $child)
      {
          $child-&gt;setParent($this);
          $this-&gt;children[] = $child;
      }
  
      public function removeChild(Child $child)
      {
          $this-&gt;children-&gt;removeElement($child);
      }
  }
  
  class Child
  {
      public function setParent(ParentClass $parent)
      {
          $this-&gt;parent = $parent;
      }
  }
  
  $parent = new ParentClass();
  $parent-&gt;addChild(new Child());
  </code></pre>
  
  <p>The problem here is that Child would be in an invalid state until you call addChild.</p>
  
  <p>A third option could be to have addChild create a new child:</p>
  
  <pre><code>class ParentClass
  {
      public function addChild()
      {
          $child = new Child($parent);
          $this-&gt;children[] = $child;
          return $child;
      }
  
      public function removeChild(Child $child)
      {
          $this-&gt;children-&gt;removeElement($child);
      }
  }
  
  class Child
  {
      public function __construct(ParentClass $parent)
      {
          $this-&gt;parent = $parent;
      }
  }
  
  $parent = new ParentClass();
  $child = $parent-&gt;addChild();
  </code></pre>
  
  <p>The problem with this is that the child constructor is exposed to developers. Also, my (Symfony) form library is probably going to hate me, causing me to have a bunch of DTO's and mappers just for a simple use case.</p>
  
  <p>There are probably even more possible ways to handle this. What is the preferred way to ensure a clean domain model?</p>