This post is part of a series I am writing on Domain Driven Design (DDD).
"An object that represents a descriptive aspect of the domain with no conceptual identity is called a VALUE OBJECT." [Evans 2003]
Basically it means that a Value Object describes the state or characteristics of an Entity, but it has no identity of its own.
Creating Value Objects
Carving out value objects from entities is quite an art. Those fields of an entity, whose values are what is important, can be moved into separate objects from entity. Value Objects can contain references to other entities and value objects.
When is a class considered as an entity and when as a value object ? This discussion explains it better than anything i have read elsewhere.
If you had looked at my previous post on entities, I had said that the entity should be stripped to its bare minimum fields. So if you were wondering what happens to the rest of the fields the answer is that, they move into value objects.
To validate if a VO created is good. Try swapping one value object with another, containing same values, and if the entity does not care and works as usual, that is sign of a good value object.
Create VO by grouping together related fields
- Group related fields of an entity together. Related fields are those where
- A field change, triggers changes in multiple other fields (or)
- A Group of fields have a collective/shared meaning
- Identify all behaviour which is based around these fields
- Move the related fields and its behaviour into its own class
Create VO for fields with format restrictions
- Identify fields in an entity, which have restrictions on values it can hold. E.g price field can be a BigDecimal with restriction that it should have 4 digit accuracy after decimal point or zipcode field has to be of a specific format
- Move such fields into separate classes with methods that enforce the restriction.
- Add methods that add to concept represented by class. For e.g we can add a currency code to price and the price object can convert its value from the default currency to USD/EUR/INR etc.
Create VO for business method arguments/return types
I picked up this tip from this video on domain value objects. The presenter says that a good starting point to identify new VO's would be to look at args and return types of domain methods. The argument here is that in most cases they are not just DTO's/some primitive type, but they represent something in the domain.
Tip: Create VO's when you define the entities. If you find that a particular VO is not adding much value, you could always fold it back into the owning entity. Never defer defining entities, since its a vey manual and painful effort. (Imagine changing all annotations, methods etc to use new VO).
Fine-Tuning the VO
Some of the interesting scenarios I faced when defining VO's
1) How to handle when, multiple entities define and use a common set of fields with some field variations ?
In the example scenario defined here, all entities, order, box and container have quantity related fields. All three have open and filled quantities, but the Container object has a maximum allowed quantity and threshold quantity. So a hierarchy of VO's was created
QuantityVO <------ LimitQuantityVO. All common fields went into the base class - QuantityVO and rest of fields went into LimitQuantityVO.
2) Do all value objects have to be immutable?
If VO's are mutable, it would make it harder to understand/control changes to the VO. It also means the VO 's methods cannot change its own state. So any mutation method on VO has to return an instance of itself with updated values and the caller needs to know how to set this VO back to the owning entity. I don't like the idea of the caller, tracking if a state change occurred or not, and then calling the corresponding update on the entity.
If your VO's rarely change, make them immutable. But making them mutable would save you lot of trouble when coding. So its elegancy vs practicality. I have done both and don't have a strong preference for one over the other. Make your choice based on which tradeoffs you can live with.
Part-2 of this post talks about how to implement VO's using java and hibernate and can be found here.
Technorati Tags: DDD, Domain Driven Design
2 comments:
Kaushik,
Good series of entries on DDD. Excellent posts! Not sure if you have already looked at DDDQuickly o InfoQ, it might help and give you some more insights
- Ravi
Hey Ravi, DDDQuickly is a good book but I felt the original book was better. I happened to look at DDDQuickly after reading Evans' book and did not find anything new in it.
Post a Comment