Circular dependency and object creation when attempting DDD

Posted by Matthew on Programmers See other posts from Programmers or by Matthew
Published on 2014-06-11T16:16:12Z Indexed on 2014/06/11 21:39 UTC
Read the original article Hit count: 394

I have a domain where an Organization has People.

Organization Entity

public class Organization {
    private readonly List<Person> _people = new List<Person>();

    public Person CreatePerson(string name) {
        var person = new Person(organization, name);
        _people.Add(person);
        return person;
    }

    public IEnumerable<Person> People {
        get { return _people; }
    }
}

Person Entity

public class Person
{
    public Person(Organization organization, string name) {
        if (organization == null) {
            throw new ArgumentNullException("organization");
        }

        Organization = organization;
        Name = name;
    }

    public Organization { get; private set; }   
    public Name { get; private set; }
}

The rule for this relationship is that a Person must belong to exactly one Organization.

The invariants I want to guarantee are:

  1. A person must have an organization

    • this is enforced via the Person's constuctor
  2. An organization must know of its people

    • this is why the Organization has a CreatePerson method
  3. A person must belong to only one organization

    • this is why the organization's people list is not publicly mutable (ignoring the casting to List, maybe ToEnumerable can enforce that, not too concerned about it though)

What I want out of this is that if a person is created, that the organization knows about its creation.

However, the problem with the model currently is that you are able to create a person without ever adding it to the organizations collection.

Here's a failing unit-test to describe my problem

[Test]
public void AnOrganizationMustKnowOfItsPeople()
{
    var organization = new Organization();
    var person = new Person(organization, "Steve McQueen");

    CollectionAssert.Contains(organization.People, person);
}

What is the most idiomatic way to enforce the invariants and the circular relationship?

© Programmers or respective owner

Related posts about c#

Related posts about object-oriented