Value Objects and Services
Today's post is a continuation of my series on Domain Driven
Design. One of my favorite parts of Domain Driven Design is how it
narrows your focus down to a handful of design patterns that will
work for just about any application you are building. I discussed
the first of these design patterns in the last post, the Entity.
This is the most important pattern for building out your ubiquitous
domain language. The next pattern to discuss is the Value
Object.
Value Objects
Just like Entities, Value Objects have attributes. The
difference between them comes in the way that you identify them. An
Entity has a unique ID and is identified by the ID. For example, an
employee has an Employee ID number. A Reservation, as we discussed
in the last post, has a Reservation Number. Entities can always be
identified by a unique ID.
Value Objects, on the other hand, contain a collection of
attributes, and it is those attributes that define the object.
Value Objects are immutable; that is, they cannot be modified after
they are created.
Examples of Value Objects in the car rental application would be
the pickup date / time. This date / time object would have
a month, day, year, hour and
minute associated with it. There is no separate unique ID
to identify it as it is defined by the the collection of its
attributes. If you modify one of those attributes, it is a
completely separate date / time object. On the other hand, if you
modify one of the attributes of a Reservation (for
example, the Car), you have modified the
Reservation object but the reservation itself is the
same.
So, the easiest way to think of the separation between Entities
and Value Objects is to determine if it has a unique ID or if its
identity is fully defined by the sum of its attributes.
An interesting thing to consider is the Rate object that I
discussed in the last post. A Rate has a price, a
location, and a vehicle. Is this an Entity or a
Value Object? Normally I would probably say that it is a Value
Object, because if you change one of those attributes, you have
changed the quoted Rate. However, having worked at a rental car
company, I know that they assign IDs to quoted rates and store
every quoted rate in the database. So it is persisted indefinitely
and is referred to by the unique ID. So, I believe a case could be
made for it either way.
Services
So far we have talked about methods that are applied directly to
Entities or Value Objects. But, what if you have a method that does
not naturally fit there? An example would be a GetRates
that takes the pickup location, pickup date and
return date, and returns a list of available rates. Where
does this method go? This is where a Service comes in. You would
create a RatesService that contains this method.
An important characteristic of services is that they are
stateless. That is, the RatesService takes some values as
input, performs an operation, returns a result, and then goes away.
This would be a good candidate for static methods in most
languages.
In Domain Driven Design these services are treated as first
class citizens alongside the Entities as you are mapping out your
domain language. Users can clearly think of a RatesService that you
throw information into and gives you meaningful results.
In the next post I will discuss the last two design patterns
used in Domain Driven Design: Repositories and Factories.