I am quite new to DDD and have some fundamental problems that i cant really understand.
Consider we have a User entity. A User has some Friend's (one to Many).
There are 2 possible solutions to fetch the friends.
Solution 1: user.getFriends()
The Problem here is that all the friends have to be loaded or I am forced to use a Proxy. If i use a Proxy it feels for me like cheating because the entity must not have an instance of the Repository. Can the Proxy have one?
Solution 2: Avoid the getFriends Method and load the Friends Based on the User Repository, like: userRepository.getFriendsOf(user)
This could sometimes be a good idea, but where to stop here? Whats about an AddressRepository for accessing user Addresses, or ?
I'm not sure that either of them are correct. I think from a DDD point of view, the code is supposed to use the Ubiquitous Language of the domain. In that regard, getters are frowned upon. Why are you getting the friends of a user? The public methods of User should reflect the ubiquitous language.
For example if your domain is a social networking site, users should have methods to update status which will internally notify friends etc. How the User knows who its friends are or how they are queried is hidden as an implementation detail.
I think you should look at it from perspective of Aggregate Roots.
In case of user.getFriends() - the user seem to be AR with associated friends which I don't think is correct. The definition of AR says "that we treat as a unit for the purpose of data changes". Friends are outside of the Boundary of user AR.
Considering the above the other option seem better - userRepository.getFriendsOf(user)
One thing to keep in mind is that you shouldn't use your domain model for querying. So you do not want to be lazy-loading or applying any other fetching strategies.
You also need to identity your aggregates. An aggregate is loaded in its entirety from the data store.
In your case if a Friend
class can only ever exist in the context of a User
then it is part and parcel of the User
and its life-cycle is linked to that of the User
. That means that when the User
is deleted (conceptually, as one probably would not want a hard delete) then the associated Friend
instances are deleted also.
So if a Friend
represent the association between users then it probably only contains the User
Id. So you could go with a list of Ids in that case. This would depend on your domain.
I would guess that you very rarely would need to load the entire list of User
instances that are friends of another user. If you need related data you could implement a light-weight query layer.