DDD implementation

My thought is that this is an example of what in relational database theory is termed a "weak entity". A Friendship could be identified solely by the identifiers of the two Users involved in the friendship, but could have its own properties such as when it was created and what type of relationship it is.

I would make this its own entity, and probably hide it behind a facade exposed by the User object:

class User {
    protected List<Friendship> _friendships { get; private set; }

    public IEnumerable<User> Friends {
        get { return _friendships.Select( /* get other user */ ); }
    }

    public void AddFriend(User otherUser) {
        // check to see if friendship exists
        // if not, create friendship
        // do other friendshippy things

        // make sure the other user knows about our friendship 
        // and gets to do its friendshippy things
        otherUser.AddFriend(this);
    }
}

I would use something like

public sealed class Username : IEquatable<Username> { /* string wrap here */ }
public class User
{
    private readonly Username _username;
    private readonly HashSet<Username> _friends;
    public User(Username username)
    {
        if (null == username) throw new ArgumentNullException("username");
        _username = username;
        _friends = new HashSet<Username>();
    }

    public Username Name { get {return _username; } }
    public void Befriend(User user)
    {
        if (null == user) throw new ArgumentNullException("user");
        _friends.Add(user.Name);
    }

    public bool IsFriendsOf(User user)
    {
        if (null == user) throw new ArgumentNullException("user");
        return _friends.Contains(user.Name);
    }
}

Note that no collection is exposed by User, according to the Law Of Demeter. In case you'd really need them I would expose an IEnumerable<Username> for friends.

Moreover, in DDD, all query and commands should be part of the ubiquituous language (this is why I used Befriend instead of AddFriend).

However, let me say that this look a bit too CRUD to require a DDD. If you don't need (at least) a domain expert to understand the domain, you don't need DDD at all. If you don't need DDD, it becomes the most expensive error in your project.

edit
Let's suppose that the domain expert states that "friendship is always reciprocal" (as per guillaume31's suggestion): by modeling idempotent commands, you can ensure such a business rule very easily. The Befriend command becomes:

public void Befriend(User user)
{
    if (null == user) throw new ArgumentNullException("user");
    if(_friends.Add(user.Name))
    {
        user.Befriend(this);
    }
}

You can always model idempotent commands with such properties, but sometimes it requires a bit more of analysis to ensure that their arguments and their internal state provide everything they need.


I think; a friendship is an aggregate root itself. It can be directly created within an application service or creation can be delegated to a domain service.

A domain service can ask user aggregates for validation, if a user specific validation requires. Or dispatch both user aggregates to friendship aggregate creator/constructor.

Then a friendship repositoy can easily return a list of friends for a given user.

Even a friendship aggregate does not have rich model or behaviour; it has a seperate consistency boundary.

Moreover, If we use eventsourcing; one can listen friendshipCreated events; and notify both users about situation.