Reputation: 2351
I'm a novice DDD'er and struggling with my first attempt to implement some of these concepts. I am writing an application to manage some marketing campaigns for different users, so a Campaign is an obvious aggregate root, but I also have Users as an aggregate root.
public class Campaign : IDomainObject
{
public virtual int CampaignId { get; set; }
public virtual string Name { get; set; }
...
public virtual int UserId { get; set; }
...
public virtual IList<CampaignEvent> Events { get; set; }
}
public class CampaignEvent
{
public virtual int CampaignEventId { get; set; }
public virtual int CampaignId { get; set; }
public virtual int UserId { get; set; }
...
}
So now when I search for a list of campaigns to display, how do I get the User's name from the Id?
If I design the model with a database-agnostic perspective, I would add a UserName string to both objects and develop from there. However, I have to be practical and consider how this will eventually go back-and-forth to the database, and it doesn't appear that this new model will work with the ORM (presently NHibernate, but I don't believe this is possible with EF either).
What are some meet-in-the-middle solutions that will accomplish the goal of getting some user information available in the object, without compromising the concepts of DDD?
Upvotes: 1
Views: 135
Reputation: 13256
If you would like to display the user name from some result set that you got from your ORM/domain model then this is a somewhat of a problem. You should not query your domain model. So how to do it then?
Well, you should try to incorporate a query/read model. A very simple query layer should be developed. To get the data, you have a couple of options. You probably want to opt for some denormalisation along the way. You could add the user id and name as a value object to your aggregate so that it is stored in your transactional store. Your query would be able to access that and have the data readily available; else your query side would need to do a join.
You could also go with eventual consistency via a truly read-specific store that contains view-specific tables.
This approach will probably bring up some more questions but it really is not as cumbersome as it may appear.
Upvotes: 1
Reputation: 81
I think the key here is that you want to change the thought process to entity to entity or value object relationships.
In the way you are modeling your classes, you have a UserId as a property and are talking about it as if it was a relationship. I think what you are wanting to convey is a relationship between the Campaign and a User, a CampaignEvent and a User, etc. It is perfectly acceptable for a Campaign to be an Aggregate Root and a User to be an Aggregate Root. When you search for a campaign, it will have a relationship to a User, so how you get the name is by getting the Name from the User entity. We don't want to speak about Id's alone, as this breaks our representation of the real entity we are trying to model. So a campaign has a/a collection user/users, and a user has a/a collection of campaign/campaigns, as opposed to a campaign has a userid.
Upvotes: 1