Note: This is part of my series on Domain Driven Design:
- Part 1: Introduction and Entities
- Part 2: Value Objects and Services
- Part 3: Repositories and Factories
- Using Domain Driven Design with a Three Tiered Architecture
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 patters that will work for just about any application you are building. I discussed the first of these design patters 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.
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 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 it’s identity is fully defined by the sum of it’s 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.
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 along side 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.