Module 93: Domain-Driven Design

Lesson 3 of 5 · 15–25 minutes

Entities and value objects

🏠The everyday picture

Two ₹500 notes are interchangeable: you don't care which one you get. But your passport is yours: even if your address changes, it's the same passport with the same number.

📘What it really is

export class Money {
  readonly paise: number;
  constructor(paise: number) {
    if (!Number.isInteger(paise) || paise < 0) throw new Error("Invalid amount");
    this.paise = paise;
  }
  add(other: Money): Money { return new Money(this.paise + other.paise); }
  format(): string { return `₹${(this.paise / 100).toFixed(2)}`; }
}

export class TimeRange {
  readonly start: Date;
  readonly end: Date;
  constructor(start: Date, end: Date) {
    if (end <= start) throw new Error("End must be after start");
    this.start = start;
    this.end = end;
  }
  overlaps(other: TimeRange): boolean {
    return this.start < other.end && other.start < this.end;
  }
}

🖱️Try it

Implement Money, TimeRange and EmailAddress value objects for the booking platform, with unit tests for their rules (negative money rejected, backwards ranges rejected, overlap detection, invalid emails rejected). Use TimeRange.overlaps to check a new availability rule doesn't clash with existing ones.

✅Quick check

What's the difference between an entity and a value object?

Show the answer

An entity has a lasting identity; a value object is defined only by its values and is immutable.

Why store money as whole paise?

Show the answer

Integers avoid floating-point rounding mistakes in money calculations.

← PreviousBounded contexts
ProLearners Assist