A breakdown of the structural differences and implementation patterns between Entities and Value Objects in Domain-Driven Design (DDD).
While both are objects containing properties and methods, they serve distinct roles regarding identity (IDs) and mutability.
1. Entity
An Entity is an object uniquely identified by an ID. Even if its internal attributes (such as name or email) change, it remains the same object as long as the ID matches. Its properties are encapsulated and modified strictly through explicit methods.
// Entity Definition: User
export class User {
// ① Identifier (ID): Unique key to distinguish the entity. Cannot be changed once set.
readonly id: string;
// Keep properties private to prevent direct external modification (Encapsulation)
private name: string;
private email: Email; // Holds a "Value Object (Email)" as a property
constructor(id: string, name: string, email: Email) {
this.id = id;
this.name = name;
this.email = email;
}
// ② State modification method: Update name
// Prevents direct assignment (e.g., user.name = "") and enforces logic through this method
changeName(newName: string): void {
// Guard clause to enforce domain rules and prevent invalid state
if (newName.length === 0) {
throw new Error("Name cannot be empty");
}
// Changing the name does not alter this.id (the identifier)
this.name = newName;
}
// ② State modification method: Update email
changeEmail(newEmail: Email): void {
// Replaces the property with a new Value Object instance
this.email = newEmail;
}
}
2. Value Object
A Value Object has no identity (ID) and is defined solely by its values. It is immutable after creation and enforces self-validation upon instantiation to prevent invalid values from existing.
// Value Object Definition: Email
export class Email {
// ① Stored value: Marked as readonly to guarantee immutability after creation
readonly value: string;
constructor(value: string) {
// Self-defense validation on instantiation
// Throws an error to prevent creating an instance with an invalid value
if (!value.includes('@')) {
throw new Error("Invalid email format");
}
this.value = value;
}
// ② Equality check method: Compares equality based on values
// Since it has no ID, equality is determined by matching property values
equals(other: Email): boolean {
return this.value === other.value;
}
}
3. Structural Differences
Key structural differences between Entities and Value Objects:
- Identifier (ID): Entities have an ID; Value Objects do not.
- Mutability: Entities are mutable via state-changing methods. Value Objects are immutable.
- Structural Relationship: Entities manage identity and can contain Value Objects as properties.
- Role: Entities manage individual lifecycles and state transitions. Value Objects ensure data type correctness and domain invariants.