DomainDrivenJSDomainDrivenJS
Home
  • Getting Started
  • Quick Start
  • DDD Fundamentals
  • Core Concepts
  • Advanced Topics
API
Examples
GitHub
Home
  • Getting Started
  • Quick Start
  • DDD Fundamentals
  • Core Concepts
  • Advanced Topics
API
Examples
GitHub
  • Introduction

    • Getting Started with DomainDrivenJS
    • Quick Start Guide
  • DDD Fundamentals

    • Introduction to Domain-Driven Design
    • Strategic Design in Domain-Driven Design
    • Tactical Design in Domain-Driven Design
    • Ubiquitous Language
  • Core Concepts

    • Understanding Value Objects
    • Working with Entities
    • Working with Aggregates
    • Working with Repositories
    • Working with Domain Events
    • Working with Specifications
    • Working with Domain Services
  • Advanced Topics

    • Extending DomainDrivenJS Components
    • Testing Domain-Driven Design Applications
    • Domain-Driven Design Best Practices
    • Domain-Driven Design Anti-Patterns

Core Domain-Driven Design Concepts

Domain-Driven Design provides a set of powerful building blocks to express your domain model in code. DomainDrivenJS makes these concepts easy to implement with a modern, functional approach tailored to JavaScript.

Quick Reference

ConceptPurposeExample
Value ObjectsImmutable objects defined by attributesMoney, Email, Address
EntitiesObjects with identity that can changeUser, Order, Product
AggregatesClusters of objects treated as a unitOrder with OrderItems
Domain EventsRecord of something significant happeningOrderPlaced, PaymentReceived
RepositoriesProvide access to aggregatesOrderRepository, ProductRepository
SpecificationsEncapsulate business rules and queriesActiveUsers, OverdueOrders
Domain ServicesOperations across multiple objectsPaymentProcessor, InventoryAllocator

Value Objects

Value objects are immutable objects defined by their attributes rather than their identity. Two value objects with the same attributes are considered equal, regardless of whether they are the same instance.

Learn more about Value Objects

// Example: Money value object
const price = Money.create({ amount: 29.99, currency: 'USD' });
const tax = Money.create({ amount: 2.40, currency: 'USD' });
const total = price.add(tax); // New Money object with amount = 32.39

Entities

Entities are objects with identity that persists across changes. Unlike value objects, entities are equal only if they have the same identity, even if their attributes differ.

Learn more about Entities

// Example: User entity
const user = User.create({
  id: 'user-123',
  name: 'John Doe',
  email: 'john@example.com'
});

// Update returns a new instance with same identity
const updatedUser = user.changeName('John Smith');

Aggregates

Aggregates are clusters of entities and value objects treated as a single unit for data changes. Each aggregate has a root entity that controls access to all members within the boundary.

Learn more about Aggregates

// Example: Order aggregate with line items
const order = Order.create({
  id: 'order-456',
  customerId: 'customer-789',
  items: [],
  status: 'DRAFT'
});

// Add item to the order
const updatedOrder = order.addItem(product, 2); 

Domain Events

Domain events represent significant occurrences within your domain that other parts of the system might be interested in. They record what happened, enabling loosely coupled communication between components.

Learn more about Domain Events

// Example: Emitting an event when order is placed
const placedOrder = order.placeOrder().emitEvent(OrderPlaced, {
  orderId: order.id,
  customerId: order.customerId,
  orderTotal: order.getTotal(),
  placedAt: new Date()
});

// Handling the event
eventBus.on(OrderPlaced, async (event) => {
  await notificationService.sendOrderConfirmation(event.customerId);
});

Repositories

Repositories provide a collection-like interface for accessing and persisting aggregates. They hide the details of data access, allowing your domain model to remain focused on business logic.

Learn more about Repositories

// Example: Saving and retrieving orders
await orderRepository.save(order);
const retrievedOrder = await orderRepository.findById('order-456');
const draftOrders = await orderRepository.findAll({ status: 'DRAFT' });

Specifications

Specifications encapsulate business rules and query logic into reusable, composable objects. They can be used for both validation and selection of domain objects.

Learn more about Specifications

// Example: Finding active premium customers
const ActiveCustomer = specification({
  name: 'ActiveCustomer',
  isSatisfiedBy: customer => customer.status === 'ACTIVE'
});

const PremiumPlan = specification({
  name: 'PremiumPlan',
  isSatisfiedBy: customer => customer.plan === 'PREMIUM'
});

// Composing specifications
const ActivePremiumCustomer = ActiveCustomer.and(PremiumPlan);
const premiumCustomers = await customerRepository.findAll(ActivePremiumCustomer);

Domain Services

Domain services encapsulate operations that don't conceptually belong to any entity or value object. They're used for operations that involve multiple domain objects or more complex business logic.

Learn more about Domain Services

// Example: Payment processing service
const paymentResult = await paymentService.processPayment({
  orderId: order.id,
  amount: order.getTotal(),
  paymentMethod: customer.preferredPaymentMethod
});

How Everything Fits Together

In a typical domain model:

  1. Value objects and entities form the building blocks of your model
  2. Aggregates group related entities and value objects into consistency boundaries
  3. Repositories store and retrieve aggregates
  4. Specifications help find the right aggregates
  5. Domain events communicate changes between aggregates
  6. Domain services coordinate operations across multiple aggregates

By using these patterns together, you can build a rich, expressive domain model that captures the complexity of your business domain while keeping your code maintainable and flexible.

Next Steps

Ready to dive deeper? Choose a concept to explore from the list above, or check out our Quick Start Guide to see these concepts in action.

Help us improve this page!
Last Updated:: 4/22/25, 11:22 AM
Contributors: Marco Müllner