views:

400

answers:

7

Hi,

I'm trying to follow DDD, or a least my limited understanding of it.

I'm having trouble fitting a few things into the DDD boxes though.

An example: I have a User Entity. This user Entity has a reference to a UserPreferencesInfo object - this is just a class which contains a bunch of properties regarding user preferences. These properties are fairly unrelated, other than the fact that they are all user preferences (unlike say an Address VO, where all the properties form a meaningful whole).

Question is - what is this UserPreferencesInfo object?

1) Obviously it's not an Entity (I'm just storing it as 'component' in fluent nhibernate speak (i.e. in the same DB table as the User entity).

2) VO? I understand that Value Object are supposed to be Immutable (so you cant cange them, just new them up). This makes complete sense when the object is an address for instance (the address properties form a meaningful 'whole'). But in the case of UserPreferencesInfo I don't think it makes sense. There could be 100 properties (Realistically) There could be maybe 20 properties on this object - why would I want to discard an recreate the object whenever I needed to change one property?

I feel like I need to break the rules here to get what I need, but I don't really like the idea of that (it's a slippery slope!). Am I missing something here?

Thanks

A: 

As far as I understand, UserPreferenceInfo is a part of User entity. Ergo User entity is an Aggregate root which is retrieved or saved using UserRepository as a whole, along with UserPreferenceInfo and other objects.

Personally, I think that UserPreferenceInfo is entity type, since it has identity - it can be changed, saved and retrieved from repository and still be regarded as the same object (i.e. has identity). But it depends on your usage of it.

It doesn't matter IMHO how object is represented in the DAL - is it stored in a separate table or part of other table. One of the benefits of DDD is persistence ignorance and is ususally a good thing.

Of course, I may be wrong, I am new to DDD too.

elder_george
Thanks for the answer - just to clarify, as it's currently set up UserPreferenceInfo doesn't have an ID, so that's why to me it seems more like a VO. But still there is the bad fit with immutability.
UpTheCreek
In my understanding, ID is not necessary to consider class an entity, since you can use other means to enforce its identity - e.g. reference to aggregate root (`User`) if there's is a single instance for a root or simply avoiding of equality comparison in business logic. IOW, identity is a logic, not structural notion.
elder_george
A: 

100 properties sounds like a lot.

Try breaking UserPreferenceInfo up into smaller (more cohesive) types, which likely/hopefully are manageable as VOs.

Martin R-L
Yeah, that was a bit of an exaggeration just to make a point. Probably wouldn't be anywhere near that, but still you wouldn't want to recreate them all.
UpTheCreek
+1  A: 

I'd say a UserPreferenceInfo is actually a part of the User aggregate root. It should be the responsibility of the UserRepository to persist the User Aggregate Root.

Value objects only need to be newed up (in your object model) when their values are shared. A sample scenario for that would be if you check for a similar UserPreferenceInfo and associate the User with that instead of Inserting a new one everytime. Sharing Value Objects make sense if value object tables would get to large and raise speed/storage concerns. The price for sharing is paid on Insert. It is reasonable to abstract this procedure in the DAL.

If you are not shraing value objects, there is nothing against updating.

Johannes Rudolph
I thought the whole point of a Value Object was that they _couldn't_ be shared. They have no concept of ID as far as I understand.
UpTheCreek
their value can be shared for the above mentioned reasons (see Evans DD p. 100)
Johannes Rudolph
Ok thanks - I'll look it up.
UpTheCreek
+3  A: 

Here's my two cents. Short answer: UserPreferenceInfo is a value object because it describes the characteristics of an object. It's not an entity because there's no need to track an object instance over time.

Longer answer: an object with 100+ properties which are not related is not very DDD-ish. Try to group related properties together to form new VOs or you might discover new entities as well.

Another DDD smell is to have a lot of set properties in the first place. Try to find the essence of the action instead of only setting the value. Example:

// not ddd 
employee.Salary = newSalary;

// more ddd
employee.GiveRaise(newSalary);

On the other hand you may very well have legitimate reasons to have a bunch of properties that are no more than getters and setters. But then there's probably simpler methods than DDD to solve the problem. There's nothing wrong with taking the best patterns and ideas from DDD but relax a little of all the "rules", especially for simpler domains.

Dala
+1  A: 

Question is - what is this UserPreferencesInfo object?

I don't know how this case is supported by NHibernate, but some ORMs support special concepts for them. For example DataObjects.Net include Structures concept. It seems that you need something like this in NH.

Alex Kofman
+3  A: 

Answer 1 (the practical one)

I'm a huge proponent of DDD, but don't force it. You've already recognised that immutable VOs add more work than is required. DDD is designed to harness complexity, but in this case there is very little complexity to manage.

I would simply treat UserPreferencesInfo as an Entity, and reference it from the User aggregate. Whether you store it as a Component or in a separate table is your choice.

IMHO, the whole Entity vs VO debate can be rendered moot. It's highly unlikely that in 6 months time, another developer will look at your code and say "WTF! He's not using immutable VOs! What the heck was he thinking!!".

Answer 2 (the DDD purist)

Is UserPreferencesInfo actually part of the business domain? Others have mentioned disecting this object. But if you stick to pure DDD, you might need to determine which preferences belong to which Bounded Context.

This in turn could lead to adding Service Layers, and before you know it, you've over-engineered the solution for a very simple problem...

Vijay Patel
+1  A: 

First time ever posting on a blog. Hope I do it right.

Anyway, since you haven't showed us the UserPreferencesInfo object, I am not sure how it's constructed such that you can have a variable number of things in it.

If it were me, I'd make a single class called UserPreference, with id, userid, key, value, displaytype, and whatever other fields you may need in it. This is an entity. it has an id and is tied to a certain user.

Then in your user entity (the root I am assuming), have an ISet.

Serenarules