Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

many to many relationship in ddd

I have two entities Publisher and SocialAccount. SocialAccount contains multiple accounts like Twitter, Facebook etc.

1 publisher can attach to many social account and 1 social account contains multiple publishers, this social account is also connected with another entity campaign. I mean both are independent entity

When creating publisher instance it is not necessary that it should subscribe to social account, it can subscribed to it at later stage.

I need to subscribe publisher to 1 or multiple social account . how do i do that

how can i convert m to m relationship into 1 to many relationship, between publisher and social account . I am not sure because i read in many places that we should avoid M to M relationship between entities.

like image 669
chandra Avatar asked Dec 06 '10 11:12

chandra


1 Answers

Let me expand on Don's answer, as I think he is leading you on the right track.

M-to-N relationships are natural, useful, and can be handled in DDD. If you require an M-to-N relationship, you don't need to try and convert it to an (or more likely multiple) M-to-1 relationship(s). Udi Dahan's acticle gives a nice example of how to handle an M-to-N relationship between entities.

First, determine which entity should contain a list of IDs of the other. Udi uses the example of job postings (Job) and job posting boards (JobBoard). Since a job can exist without a job board and a job board cannot exist without jobs, JobBoard is chosen as the aggregate root and will contain a List<Job>. This might seem like an M-to-1 relationship, but, as each Job can be in the list for multiple JobBoards, it is really M-to-N.

In your case of SocialAccount and Publisher, I recommend something like this in C#:

public class Publisher
{
    public int ID {get; private set;}
    
    private readonly IList<int> _AssignedSocialAccounts = new List<int>();
    public IEnumerable<int> AssignedSocialAccounts { get { return this._AssignedSocialAccounts; } }
    
    public Publisher(int ID) //Pass required fields to the constructor.
    {
        this.ID = ID;
    }
    
    public AssignSocialAccount(int SocialAccountID)
    {
        if(!this._AssignedSocialAccounts.Contains(SocialAccountID))
            this._AssignedSocialAccounts.Add(SocialAccountID);
    }
}

public class SocialAccount
{
    public int ID {get; private set;}
    
    public SocialAccount(int ID) //Pass required fields to the constructor.
    {
        this.ID = ID;
    }
}

(This example uses domain encapsulation similar to Jimmy Bogard's Wicked Domain Models.)

Note that I chose Publisher to be the aggregate root since a SocialAccount can exist on its own, but a Publisher has no meaning without the existence of a SocialAccount.

Also note that I am passing around unique IDs, not references to the objects themselves. This is a common approach in DDD and allows for the lazy loading of related entities, although the tradeoff is you have to call the repository to get the entities when you want to access them.

This approach also means that you do not have all SocialAccounts as a single enumeration. They are split up between the various Publishers. To get a list of all SocialAccounts will require a separate query.

like image 105
Justin J Stark Avatar answered Oct 04 '22 14:10

Justin J Stark