Value Object
A domain object defined by its attributes rather than a unique identity, always kept in a valid state.
A value object is a domain type that has no identity of its own. Two value objects are equal if all their attributes are equal. Think of a postal address, a money amount, or a time slot. You don't care which address instance it is, only what it contains.
This is in contrast to entities, where identity matters. Two users with the same name are still different users. But two Money{Amount: 100, Currency: "USD"} values are interchangeable.
In Go, value objects are typically structs with unexported fields and a constructor that validates invariants. The constructor is the only way to create the object, so every instance is guaranteed to be valid.
type Money struct {
amount int
currency string
}
func NewMoney(amount int, currency string) (Money, error) {
if amount < 0 {
return Money{}, errors.New("amount must not be negative")
}
if currency == "" {
return Money{}, errors.New("currency is required")
}
return Money{amount: amount, currency: currency}, nil
}
Because fields are unexported, no one can create a Money with a negative amount or an empty currency. The struct is always in a valid state. This is one of the most practical ideas from DDD: instead of scattering validation across handlers, services, and repositories, you push it into the type itself.
Value objects are also immutable. Operations on them return new instances rather than modifying existing ones. This makes them safe to pass around, compare, and use as map keys.
The practical benefit is that once you hold a value object, you know it's valid (unless it's zero-value). Your code doesn't need defensive checks everywhere. If a value object exists, it's correct. This removes an entire category of bugs.
References
- Introduction to DDD Lite: When microservices in Go are not enough — Introduces value objects as a core DDD building block in Go. Shows how to keep domain types always in a valid state by using constructors and unexported fields.
- Common Anti-Patterns in Go Web Applications — Lists value objects alongside aggregates and repositories as DDD-inspired techniques that solve common anti-patterns in Go web applications.
- DDD: A Toolbox, Not a Religion — Mentions value objects as part of the DDD toolbox. Even in the simplest systems, at least one DDD idea like value objects tends to apply.