В чем заключается паттерн Event Sourcing?

«В чем заключается паттерн Event Sourcing?» — вопрос из категории Паттерны, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Event Sourcing (Прослеживаемость событий) — это паттерн проектирования, при котором состояние сущности не хранится напрямую, а восстанавливается путем последовательного применения потока всех произошедших с ней событий. Каждое изменение сохраняется как неизменяемое событие (event) в журнале.

Основная идея: Состояние = Σ(События).

Пример (Упрощенная реализация счета):

// События — источник истины
public class AccountOpenedEvent { private String accountId; }
public class MoneyDepositedEvent { private BigDecimal amount; }
public class MoneyWithdrawnEvent { private BigDecimal amount; }

// Агрегат, который восстанавливает состояние из событий
public class Account {
    private String id;
    private BigDecimal balance = BigDecimal.ZERO;
    private List<Event> changes = new ArrayList<>();

    // Восстановление из истории
    public Account(List<Event> history) {
        for (Event event : history) {
            apply(event);
        }
    }

    // Применение нового события
    public void deposit(BigDecimal amount) {
        MoneyDepositedEvent event = new MoneyDepositedEvent(amount);
        apply(event);
        changes.add(event); // Сохраняем для последующей записи
    }

    private void apply(Event event) {
        if (event instanceof MoneyDepositedEvent e) {
            balance = balance.add(e.amount());
        }
        // ... обработка других типов событий
    }
    // Геттер для balance
}

Преимущества:

  • Полный аудит: Журнал событий — это полная история всех изменений.
  • Воспроизведение состояния: Можно восстановить состояние на любой момент в прошлом.
  • Интеграция: События естественным образом используются для обмена данными между системами (Event-Driven Architecture).
  • Отладка: Легче отследить, как система пришла к текущему состоянию.

Сложности: Усложняет запросы (требуются проекции), увеличивает объем хранимых данных.