Software Engineering

Domain-Driven Design

Цели урока

  • Understand that DDD solves the communication gap between business and engineers, not just code
  • Know the core tactical patterns: Entity, Value Object, Aggregate, Domain Event
  • Treat a Bounded Context as the boundary of one data model, not as one service
  • Use the Ubiquitous Language in code, tests, and conversations with the business
  • Tell apart situations where DDD pays off (complex domain) from those where it is overkill (CRUD)

Предварительные знания

  • Basic OOP: classes, encapsulation, inheritance
  • SOLID and a working grasp of common architecture patterns
  • Experience working on an app with non-trivial business logic (banking, e-commerce, logistics)

2003: Eric Evans publishes 'Domain-Driven Design'. 560 pages about how code should reflect business reality, not just technical structure. 20 years later, Bounded Context became the unit of microservice decomposition for Amazon, Uber, and Shopify. The book preceded the microservices revolution - and explained it retrospectively.

  • **Amazon**: each service corresponds to a Bounded Context - Orders, Payments, Inventory, Recommendations. Jeff Bezos's 'two-pizza team' aligns with DDD's context boundaries.
  • **Uber**: the Driver context and Rider context have different models of Trip - for the driver it is route and earnings, for the rider it is ETA and price. Same domain word, completely different models.
  • **Shopify**: the Product model in the Storefront context (SEO, photos, description) at its core differs from Product in the Inventory context (SKU, warehouse location, reorder point).

Bounded Context

Bounded Context (bounded context) is an explicit boundary within which a domain model is consistent and has a single language (Ubiquitous Language). The same word can mean different things in different contexts: 'Product' in the catalog context (SEO, photos) is different from 'Product' in the warehouse context (weight, location, stock level).

Context Map shows relationships between contexts: Shared Kernel (two contexts share part of the model - tight coupling, used sparingly), Customer-Supplier (one context depends on the other's API), Anticorruption Layer (translation between contexts that protects the model from external concepts).

An e-commerce system has one large Product model used in catalog, warehouse, and billing. What problem does this cause?

Aggregates

An Aggregate is a cluster of objects (Entities and Value Objects) treated as a unit of consistency. Aggregate Root is the only external access point. No external code can reference internal entities of the aggregate directly - only through the Root. This enforces invariants.

Aggregate size affects performance and concurrency. A large aggregate (Order with 1000 items) - one transaction blocks all modifications. A small aggregate - parallel modifications possible. Rule: small aggregates, consistency within one aggregate, eventual consistency between aggregates.

An external service wants to update an OrderItem price directly by its ID (without going through Order). Why is this a DDD violation?

Entities and Identity

An Entity is an object whose identity is determined not by attributes but by a unique ID. Two Customer objects with the same name and email are different Entities if they have different IDs. Identity persists through state changes: a customer who changes name is still the same customer.

Repository pattern - abstraction for aggregate storage. Repository accepts and returns fully formed aggregates. No partial updates (UPDATE SET single_field) - the repository saves the complete aggregate state. This enforces the Aggregate Root as the only consistency boundary.

OrderRepository.save() receives an Order aggregate and saves it. How should the transaction work?

Value Objects

A Value Object is an object whose identity is determined by the totality of its attributes, not an ID. Two Money(100, USD) objects are equal and interchangeable. Value Objects are immutable - operations return a new object rather than modifying the existing one.

Examples of Value Objects: Money (amount + currency), Address (street, city, country), Email, PhoneNumber, DateRange, Coordinates. Value Objects eliminate primitive obsession: instead of String email and String phone in a Customer, use Email and PhoneNumber types with built-in validation.

DDD is only for microservices - in a monolith it is excessive

DDD applies regardless of physical architecture. Bounded Contexts can be implemented as separate modules within a monolith (Modular Monolith). Aggregates and Value Objects improve code quality regardless of deployment topology.

DDD is a design approach, not a deployment strategy. A team can practice DDD in a monolith for years and then split into microservices along the Bounded Context boundaries - this is exactly how Netflix and Amazon did it.

What distinguishes an Entity from a Value Object in DDD?

Key Ideas

  • **Bounded Context**: explicit boundary with a unified language - one concept (Customer) means different things in different contexts, and that is correct and intentional.
  • **Aggregate**: cluster of objects as a consistency unit, Aggregate Root - the only modification point, enforces business invariants.
  • **Entity vs Value Object**: Entity identified by ID (who it is), Value Object by attribute values (what it is) - immutable, equality by value.

Related Topics

DDD defines the conceptual architecture for many patterns:

  • Event Sourcing and CQRS — Domain Events are the mechanism for integration between Bounded Contexts - events carry information across context boundaries without tight coupling
  • Monolith vs Microservices — Bounded Context is the decomposition unit: each microservice should correspond to one Bounded Context - this is what prevents service boundaries from becoming arbitrary

Вопросы для размышления

  • How to determine the correct Aggregate size - too large creates concurrency problems, too small requires eventual consistency everywhere?
  • Ubiquitous Language requires constant dialogue between developers and business. How to organize this when business stakeholders are not available daily?
  • When is DDD overhead justified, and when is a simple CRUD model better?

Связанные уроки

  • db-01-intro
Domain-Driven Design

0

1

Sign In