Imagine you build a social network. There are users who can add other users as friends. How do you model this in DDD? Naturally you cannot simply have a list of friends in the <
That would very much depend on where you consistency boundaries need to be. Which would also therefore depend on what business rules you have.
While Meta-Knight has FriendRequest in the same Aggregate I would have it as its own and use events to communicate between the Aggregates therefore making a Person and there FriendRequests eventually consistent. This would allow you to do something like.
public class DomainRouter {
public void When(FriendRequestCreated event)
{
//Send command to each Person to record request
}
public void When(FriendRequestAccepted event)
{
//Send command to Person to record request accepted and add friend.
//Send comamnd to Person who accepted to add Friend
}
public void When(FriendRequestDeclined event)
{
//Send command to update Friend request on person.
//Send command to Person who declined to record they have declined?
}
}
The information on Person would therefore just be a record of state. The FriendRequest Aggregate would be where all the process actually happens.
What is important in DDD is to think about behavour. A FriendRequest can be Requested, Withdrawn, Accepted and Declined. What can a Person do? Does a Person need to be DDDd or could you make it nice and simply CRUD + store info into graph database etc.
Maybe you want to model it that in a way where you can go person.requestFriendAcceptance(Person id) in which case the router would probably just handle the FriendRequestCreated event by notifying the friend of a FriendRequest.
A User
could have a list of Friend
s. A Friend
could consist of a UserId, FriendType, GroupId, etc.
A User
could also have a list of FriendRequest
s. A FriendRequest
could have a UserId, RequestMessage, RequestStatus etc.
User
, Friend
and FriendRequest
could all be part of the same Aggregate. But there could be some duplication by doing so. Another option would be to have one FriendRequest for both users involved, and each user would have a list of received and sent FriendRequest
IDs.
This is just to give you some ideas because in DDD, your design will depend highly about how your app will work, and which features are needed. ;-)
hmm... Actually it's quite easy to do what you've asked, and your situation is a standard one. You don't have to store actual User
object in Friendslist
of your User
aggregate, just put there IDs of users who are friends for the User
.
This is one of the rules of aggregate implementation proposed by Vaugh Vernon: link to other aggregate and entities by their ID. So no loops, just list of IDs.
In that situation then somebody become a friend to somebody you have to change two aggregates at one time. It can be undesirable behavior because change can't occur instantly in one transaction. But for this case you have Domain Events and friend requests can be easily modeled: your aggregates can communicate with each other with FriendshipRequested
, FriendshipAccepted
, FriendshipCancelled
or FriendshipDeclined
events and change their state correspondingly.
In this case you also receive logs and notifications for free.