Easy📖Теория1 min

Шаг 7: Domain Events

Создание доменных событий OrderCreated, OrderConfirmed, OrderCancelled: зачем нужны события и как они отделяют побочные эффекты от бизнес-логики

Шаг 7: Domain Events

Доменное событие фиксирует: «что-то важное произошло». Когда заказ подтверждён, нужно отправить email, зарезервировать товар, обновить статистику. Вместо того чтобы засунуть всё это в метод Confirm(), Order просто публикует событие, а обработчики реагируют на него.

Зачем события

Без событий: Order.Confirm() знает про email, склад, статистику -- нарушение SRP и OCP. С событиями: Order говорит «я подтверждён», а кто хочет -- тот слушает.

OrderCreatedEvent.cs

В папке Events:

using OrderManagement.Domain.Common;

namespace OrderManagement.Domain.Events;

public record OrderCreatedEvent(
    Guid OrderId, string CustomerId) : IDomainEvent
{
    public Guid EventId { get; } = Guid.NewGuid();
    public DateTime OccurredOn { get; } = DateTime.UtcNow;
}

record -- неизменяемый тип с автоматическим Equals и ToString(). Свойства EventId и OccurredOn инициализируются один раз при создании.

OrderConfirmedEvent.cs

using OrderManagement.Domain.Common;
using OrderManagement.Domain.ValueObjects;

namespace OrderManagement.Domain.Events;

public record OrderConfirmedEvent(
    Guid OrderId, Money TotalAmount) : IDomainEvent
{
    public Guid EventId { get; } = Guid.NewGuid();
    public DateTime OccurredOn { get; } = DateTime.UtcNow;
}

OrderCancelledEvent.cs

using OrderManagement.Domain.Common;

namespace OrderManagement.Domain.Events;

public record OrderCancelledEvent(
    Guid OrderId, string Reason) : IDomainEvent
{
    public Guid EventId { get; } = Guid.NewGuid();
    public DateTime OccurredOn { get; } = DateTime.UtcNow;
}

Теперь Order.cs компилируется без ошибок -- все события определены.

Проверь себя

🧪

Зачем использовать record вместо class для событий?

🧪

Когда генерируется OrderCreatedEvent?

🧪

Как Domain Events помогают соблюдать принцип Open/Closed?