Tuesday, October 28, 2008

DDD - Making meaningful relationships

A recent discussion on the DDD forum made me want to post about what I consider to be an under-appreciated aspect of domain modelling, namely relationships. In the thread Randy Stafford said the following:

Note that RoleRegistration is an example of a Relationship Object – arguably a fourth archetype of domain object alongside Entity, Value Object, and Aggregate.

I couldn't agree more with this, in a domain model I worked on recently we had a stack of very useful and very meaningful relationship objects that served a range of purposes.

For example if a Client has Accounts then it is possible that you can get away with just having that as a direct relationship but its equally possible that the relationship itself is meaningful and carries its own data/behavior. In this case you might have a type association with the relationship that would explain if the Client owns the Account, or whethery just manage it, or whether they are actually just one of several owners.

Aggregates

You need to consider aggregate boundaries especially carefully when using Relationship Objects.

In the case of an association between a Client and an Account the relationship probably belongs to the Client aggregate.

Then again if you choose to model the association between a Client and SalesAdvisor using a full blown party/role/relationship approach then things become a big more complex. Are all parties and roles and relationships different aggregates or does a relationship own the two roles it composes?

If its the latter then you may be breaking an aggregate design rule because the party now refers to a piece of the relationship aggregate other than root.

Temporal Associations

Another common case is that the relationship is temporal which brings with it a lot of complexity and should only be done with extreme care.  If your sure you need temporal associations then you will find Martin Fowlers patterns invaluable.

Encapsulating Relationships

Most of the relationships have real meaning in their own right but sometimes they are just an artifact of the design, in those cases you can demote the associations to being just an encapsulated detail.

Take the association between Client and Account, maybe when you ask for the Accounts for a Client you want to get the Account objects rather than the ClientAccountRelationship objects.

If this were the case you could keep the ClientAccountRelationship class, which has its own data/behaviour and makes mapping easier, but entirely hide it from users of the domain. One way to do this is to create custom collection called ClientAccounts and have it wrap an IList<ClientAccountRelationship> whilst acting like it is just a simple IList<Account>, it can also provide helpful methods like FindPrimaryOwner.

Summary

I mention all of this because when I got started with DDD relationship objects bothered me especially as we were working with a legacy database and I saw the relationship objects as being a problem caused by the number of join tables. At the time my plan was to get rid of a lot of them by taking advantage of NHibernate magic.

However as I got a bit more experience I realized that they were key and although we encapsulated some (when they were just an artifact of the design) we made others totally key parts of the design. In both cases the relationships themselves were very useful.

Share This - Digg It Save to del.icio.us Stumble It! Kick It DZone

3 comments:

  1. Anonymous7:00 pm

    I have had the chance to work in a pretty good data model based upon the experience as found in the Universal Data Models (http://www.univdata.com/article.htm) that was mapped to the domain layer using NHibernate. I tried to use it at a project but I was flamed for being too "big up-front design" when I thought using such relationship entities can allow a better decoupled design between aggregate roots.

    ReplyDelete
  2. Yeah I used the book by Len Silverston as one of the sources when evaluating the party archetype a year or two back.

    I can see the whole "big up-front design" thing but ultimately you could also argue its NIH, if there's a good pattern out there use it or learn from it. Did you manage to convince them in the end?

    Definitely agree on the coupling, if the relationships exist making them a concrete part of your model definitely has positive effects.

    ReplyDelete
  3. Hi colin, i'm planning to design simple framework but my target is to avoid table relation, meaning that the relation only handle in domain not in database. And the relation for all domain is inject when needed using DI. What do you think?

    ReplyDelete