13 Nov 2023
Key characteristics of value objects in Domain-Driven Design (DDD) :
- Immutability: Value objects are typically immutable once created, ensuring their state doesn't change, maintaining consistency.
Examples:
-
Money Value Object: The
Moneyvalue object represents a monetary amount with a specific currency. Immutability is maintained by not providing any setters for theamountandcurrencyproperties. Once aMoneyobject is created, its state cannot be changed.public class Money { private final BigDecimal amount; private final Currency currency; public Money(BigDecimal amount, Currency currency) { this.amount = amount; this.currency = currency; } public BigDecimal getAmount() { return amount; } public Currency getCurrency() { return currency; } } -
PhoneNumber Value Object: The
PhoneNumbervalue object represents a phone number. Immutability is ensured by not providing any setters for thenumberproperty. Once aPhoneNumberobject is instantiated, its value cannot be modified.public class PhoneNumber { private final String number; public PhoneNumber(String number) { this.number = number; } public String getNumber() { return number; } }
-
Equality based on Value: Equality of value objects is determined by their internal state or values, not by identity. If two value objects have the same values, they are considered equal.
Examples:
-
EmailAddress Value Object: The
EmailAddressvalue object represents an email address. Equality is determined based on theaddressproperty. TheequalsandhashCodemethods are overridden to compare and hash based on the email address.public class EmailAddress { private final String address; public EmailAddress(String address) { this.address = address; } @Override public boolean equals(Object obj) { // Implementation for equality based on 'address' } @Override public int hashCode() { // Implementation for hashing based on 'address' } } -
Point Value Object: The
Pointvalue object represents a two-dimensional point. Equality is determined based on thexandycoordinates. TheequalsandhashCodemethods are overridden accordingly.public class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object obj) { // Implementation for equality based on 'x' and 'y' } @Override public int hashCode() { // Implementation for hashing based on 'x' and 'y' } }
-
-
No Identity: Unlike entities, value objects don't have a distinct identity; they're identified by their attributes rather than a unique identifier. Examples:
-
Color Value Object: The
Colorvalue object represents an RGB color. It does not have a distinct identity; equality is based on thered,green, andbluecomponents.public class Color { private final int red; private final int green; private final int blue; public Color(int red, int green, int blue) { this.red = red; this.green = green; this.blue = blue; } } -
DateRange Value Object: The
DateRangevalue object represents a range of dates. It does not have a distinct identity; equality is based on thestartDateandendDate.public class DateRange { private final LocalDate startDate; private final LocalDate endDate; public DateRange(LocalDate startDate, LocalDate endDate) { this.startDate = startDate; this.endDate = endDate; } }
-
-
Shared and Immutable: They're designed to be shared and reused across the domain model, promoting immutability to prevent unintended modifications. Examples:
-
Address Value Object: The
Addressvalue object represents a postal address. It is designed to be shared across entities and is immutable to prevent unintended modifications.public class Address { private final String street; private final String city; private final String zipCode; public Address(String street, String city, String zipCode) { this.street = street; this.city = city; this.zipCode = zipCode; } } -
Country Value Object: The
Countryvalue object represents a country. It is designed to be shared and immutable, ensuring consistency across the domain model.public class Country { private final String name; private final String code; public Country(String name, String code) { this.name = name; this.code = code; } }
-
-
Small-Scale and Coherent: They encapsulate a small set of related attributes that form a coherent whole, representing a specific concept within the domain.
Examples:
-
Temperature Value Object: The
Temperaturevalue object represents a temperature with a specific unit. It encapsulates a small set of related attributes (valueandunit) that form a coherent concept within the domain.public class Temperature { private final double value; private final TemperatureUnit unit; public Temperature(double value, TemperatureUnit unit) { this.value = value; this.unit = unit; } } -
Duration Value Object: The
Durationvalue object represents a time duration. It encapsulates a small and coherent concept related to time (seconds).public class Duration { private final long seconds; public Duration(long seconds) { this.seconds = seconds; } }
-
-
Side-Effect-Free: Using value objects in operations or calculations does not produce side effects or change any external state.
Examples:
-
Percentage Value Object: The
Percentagevalue object represents a percentage. It is designed to be side-effect-free, meaning that using it in operations or calculations does not produce any unintended side effects.public class Percentage { private final double value; public Percentage(double value) { this.value = value; } } -
Ratio Value Object: The
Ratiovalue object represents a mathematical ratio. It is side-effect-free, ensuring that operations involving it do not produce any external side effects.public class Ratio { private final int numerator; private final int denominator; public Ratio(int numerator, int denominator) { this.numerator = numerator; this.denominator = denominator; } }
-
-
Composability: Value objects can be combined to create more complex structures or as part of entity attributes.
Examples:
-
GeoLocation Value Object: The
GeoLocationvalue object represents a geographic location with latitude and longitude. It is composable, allowing it to be combined with other value objects, such asPoint, to create more complex structures.public class GeoLocation { private final double latitude; private final double longitude; public GeoLocation(double latitude, double longitude) { this.latitude = latitude; this.longitude = longitude; } } -
Dimensions Value Object: The
Dimensionsvalue object represents the dimensions of an object in three-dimensional space. It is composable, allowing it to be combined with other value objects, such asPoint, to create more complex structures.public class Dimensions { private final double length; private final double width; private final double height; public Dimensions(double length, double width, double height) { this.length = length; this.width = width; this.height = height; } }
-