Ответ
Event Sourcing — это архитектурный паттерн, при котором состояние приложения определяется последовательностью событий. Его стоит применять в следующих сценариях:
- Требуется полный аудит и трассируемость: Например, в финансовых системах, где критично знать не только текущий баланс, но и всю историю его изменений (кто, когда и почему изменил).
- Необходима возможность "переиграть" события: Для отладки сложных бизнес-процессов, создания снимков состояния на произвольную дату или построения новых проекций данных.
- Сложная предметная область с агрегатами: Когда бизнес-логика сосредоточена вокруг агрегатов, чье состояние меняется в результате явных событий (например,
OrderPlaced,PaymentReceived,ItemShipped).
Практический пример на C#:
// Доменное событие
public record OrderCreatedEvent(Guid OrderId, string CustomerId, DateTime CreatedAt);
public record OrderStatusChangedEvent(Guid OrderId, string OldStatus, string NewStatus, DateTime ChangedAt);
// Агрегат, использующий Event Sourcing
public class OrderAggregate
{
public Guid Id { get; private set; }
public string Status { get; private set; } = "New";
private readonly List<object> _pendingEvents = new();
// Восстановление состояния из истории событий
public void LoadFromHistory(IEnumerable<object> pastEvents)
{
foreach (var e in pastEvents)
{
Apply(e);
}
}
// Публичный метод для изменения статуса
public void ChangeStatus(string newStatus)
{
if (Status == newStatus) return;
// Генерируем событие
var evt = new OrderStatusChangedEvent(Id, Status, newStatus, DateTime.UtcNow);
Apply(evt);
_pendingEvents.Add(evt); // Сохраняем для последующей записи
}
// Применение события к состоянию агрегата
private void Apply(object evt)
{
switch (evt)
{
case OrderCreatedEvent created:
Id = created.OrderId;
break;
case OrderStatusChangedEvent statusChanged:
Status = statusChanged.NewStatus;
break;
}
}
// Получение новых событий для сохранения
public IEnumerable<object> GetPendingEvents() => _pendingEvents;
}
Основной компромисс: Паттерн добавляет сложность (хранение и обработка потока событий), но дает беспрецедентную гибкость для анализа и реконструкции данных.