I'm developing real-time chat functionality as part of an application. As per my initial structure I had 3 Domain Objects as part of this new context:
Thread
(aggregate root)ThreadMessage
(entity, part of theThread aggregate
as a collection; has a ParticipantId to know it's sender)ThreadParticipant
(entity, part of theThread aggregate
as a collection)
The problem arose when I realised I need the Thread
and ThreadParticipant
relationship to be logically (and in the persistance store) many-to-many. My User
(from the Identity bounded context) will hold a reference to a ThreadParticipant
's ID.
The more I thought the less sense it made for the ThreadParticipant
to be a child entity in Thread
as it it can obviously live on it's own being in a many-to-many relationship with Thread
.
My question is is it bad to create a separate bounded context with ThreadParticipant
as the aggregate root, which will hold a collection of Thread
IDs, for example. And if so, what will happen to the Message
entity from the Thread
aggregate root- it will hold a reference to the Participant
aggregate root which will cause a circular reference between both contexts.
1 Answer 1
There are no issues in having a many-to-many relationship between Theads an Participants. The decision is not about the relationship but instead about the consistency that you want to enforce.
Should you be able to retrieve all threads and look at their participants?
Should you be able to retrieve all participants and look all their thread?
given a participant, should you be able to access all threads info even if a thread as been deleted?
given a thread, if a partcipant changes its nickname after joining, should you still be able to watch old nickname into thread participants list?
well these are the questions that make you understand if thread and participants are two different aggregates. If so, they should be as loosely coupled as possible
Final note about bunded context: as of now, we've talked about information consistency and we have used aggregates to define boundaries around those consistent information. Bounded Context are not the same as aggregates. Aggregates enforce logical consistency, bounded context enforce semantic consistency. You could have multiple aggregates in a bounded context, but each aggregate has its unique meaning in this context. You've choose to have "Users" and "Participants" into your application. Well, it's clear that a Participants IS a user, but in the identity BC, being a user means to be identified in the system, in chat BC being a users means interact with other users. So, same concept, different meaning, but you're still interested on keeping some form of consistency between the two BCs
void main()