In Domain-Driven Design (DDD), a value object is an object that represents a concept or an idea in the domain model that does not have a unique identity or a lifespan beyond that of the object’s containing entity.
A value object is defined by its attributes, and it is immutable, meaning that its state cannot be changed after it has been created. Value objects are typically used to represent quantities, measurements, dates, currency, or other concepts that can be expressed as a combination of attributes.
Because value objects do not have a unique identity, they can be freely copied and shared without affecting the consistency of the domain model. Value objects are also compared based on their attributes rather than their identity, which allows for more flexible and intuitive comparisons.
In software implementation, value objects are often created as immutable classes with no identity of their own, and they are typically implemented as part of the containing entity or aggregate. By using value objects in the domain model, developers can create more expressive, maintainable, and extensible code that better reflects the business domain.
An example
Let’s say you are building an e-commerce website, and you have a requirement to represent a price in the domain model. A price is a good candidate for a value object because it can be represented as a combination of attributes (e.g. currency and amount) and does not have a unique identity of its own.
Here’s an extremely simple example of a Price value object in Java:
class Price {
private final Currency currency;
private final BigDecimal amount;
public Price(Currency currency, BigDecimal amount) {
this.currency = currency;
this.amount = amount;
}
public Currency getCurrency() {
return currency;
}
public BigDecimal getAmount() {
return amount;
}
// Other methods and business logic specific to the Price concept
}
In this example, the Price value object has two attributes: currency and amount. The currency attribute represents the currency of the price (e.g. USD, EUR, etc.), while the amount attribute represents the numerical value of the price. The Price object is immutable, and its state cannot be changed after it has been created. The Price object also defines methods to retrieve its attributes (e.g. getCurrency() and getAmount()), as well as other methods specific to the Price concept (e.g. add() or subtract() methods).
By using a Price value object, we can ensure that prices are represented consistently throughout the domain model, and we can perform more flexible and intuitive comparisons and calculations on prices.
Value object versus entity
It is possible for a value object in one solution to be an entity in another solution. The distinction between value objects and entities is context-dependent and based on the needs of the domain model.
In one context, an object may be considered a value object because it is defined by its attributes and does not have a unique identity. However, in a different context or a different solution, the same object may be considered an entity because it has a unique identity and can be persisted in a database or have a lifespan beyond the containing object.
For example, consider a Person object in a human resources domain. In one context, the Person object may be considered a value object because it is defined by its attributes, such as name, birth date, and social security number. However, in a different context or a different solution, the Person object may be considered an entity because it has a unique identity and can be persisted in a database or used across different bounded contexts.
Ultimately, the choice of whether to model an object as a value object or an entity depends on the needs of the domain model and the specific requirements of the software solution being developed. The important thing is to choose the right modeling concepts to accurately represent the domain and provide a flexible and maintainable software solution.