# DDD Building Blocks (Tactical Patterns)

**In short:** DDD building blocks are modeling elements: entities, value objects, aggregates, domain events, domain services and repositories. They align code with business problems and share business vocabulary.

## Explanation

Domain-Driven Design (see Domain-Driven Design) offers building blocks for modeling business logic. The patterns themselves are not the point. The value lies in organizing code around the business problem and using the same business terms everywhere. That shared vocabulary is the ubiquitous language (see Ubiquitous Language).

**Entity.** An entity has a unique identity that persists over time. Two instances with the same identity are the same thing, even when their attributes change. Entities should also hold behavior: validation, state transitions and business rules. An entity with only data is called an anemic domain model, and you should avoid it. See Entity.

**Value object.** A value object has no identity. Objects with equal attribute values are interchangeable. Value objects are immutable. To change one, you create a new instance that replaces the old one. Immutability avoids aliasing bugs, where one object is shared and silently changed. See Value Object and Entity and Value Object.

**Aggregate.** An aggregate is a cluster of domain objects treated as one unit. It is a consistency boundary that protects transactional rules. Exactly one entity is the root, and the aggregate is looked up through it. See Aggregate.

**Domain event.** A domain event captures something significant that happened in the domain. Aggregates raise events after they change state. Events are the main way to coordinate work across aggregate boundaries. See Domain Event.

**Domain service.** A domain service is a stateless object. It holds logic that does not naturally belong to one entity or value object. It encapsulates rules that span several entities or aggregates. See Domain Service.

**Repository.** A repository sits between the domain and the data mapping layers. It offers a collection-like interface to domain objects and hides how they are stored.

**Layering.** The domain layer holds business concepts and rules. It must not depend on other layers. Storing data is delegated to the infrastructure layer. See Domain Layer Separation.

## Example

A library models a reader who borrows books. Reader is an aggregate root and an entity: the same reader stays the same reader after a change of address. Each loan sits inside the reader aggregate. A loan period (start and due date) is a value object. Extending a loan creates a new period instead of editing the old one. A lending service holds the rule for lending a book, because it involves both a reader and a book. When a loan is made, a "book lent" event is raised so other parts can react. A reader repository loads and saves readers without exposing the database.

## Trade-offs

The facts here describe what each pattern does. They do not say when a pattern costs more than it gives. Treat the patterns as a means, not a goal. Their value comes from alignment with the business problem and shared terms, not from using every pattern.

Generic library example: an aggregate with a root entity, a value object, a domain service and a repository.

```plantuml
@startuml
class Reader <<aggregate root>>
class Loan <<entity>>
class LoanPeriod <<value object>>
class LendingService <<domain service>>
interface ReaderRepository <<repository>>
Reader "1" *-- "0..*" Loan
Loan *-- LoanPeriod
LendingService ..> Reader
ReaderRepository ..> Reader : loads and saves
@enduml
```

## Checks

- Each entity in the domain model has a unique identity, and its validation and state transitions live in the entity itself.
- Value objects are immutable and are replaced by new instances when they change.
- Each aggregate names exactly one root entity and states the consistency rules it protects.
- Logic spanning several entities or aggregates sits in a stateless domain service.
- The domain layer does not depend on other layers, and persistence is delegated to infrastructure.

## Related

- [Domain-Driven Design](https://arc.fuet.ch/concepts/domain-driven-design/domain-driven-design.md)
- [Entity](https://arc.fuet.ch/concepts/domain-driven-design/entity.md)
- [Value Object](https://arc.fuet.ch/concepts/domain-driven-design/value-object.md)
- [Aggregate](https://arc.fuet.ch/concepts/domain-driven-design/aggregate.md)
- [Domain Event](https://arc.fuet.ch/concepts/domain-driven-design/domain-event.md)
- [Domain Service](https://arc.fuet.ch/concepts/domain-driven-design/domain-service.md)
- [Domain Layer Separation](https://arc.fuet.ch/concepts/domain-driven-design/domain-layer.md)
- [Ubiquitous Language](https://arc.fuet.ch/concepts/domain-driven-design/ubiquitous-language.md)

## Sources

- [Designing a DDD-oriented microservice - .NET | Microsoft Learn](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/ddd-oriented-microservice) — learn.microsoft.com, accessed 2026-11-09
- [Use Tactical DDD to Design Microservices - Azure Architecture Center | Microsoft Learn](https://learn.microsoft.com/en-us/azure/architecture/microservices/model/tactical-domain-driven-design) — learn.microsoft.com, accessed 2026-11-09
- [Repository](https://martinfowler.com/eaaCatalog/repository.html) — martinfowler.com, accessed 2026-11-09
- [Value Object](https://martinfowler.com/bliki/ValueObject.html) — martinfowler.com, accessed 2026-11-09
- [D D D_ Aggregate](https://martinfowler.com/bliki/DDD_Aggregate.html) — martinfowler.com, accessed 2026-11-09
- [Domain Event](https://martinfowler.com/eaaDev/DomainEvent.html) — martinfowler.com, accessed 2026-11-09
