Ответ
Event Sourcing (Хранение событий) — это архитектурный паттерн, при котором состояние приложения определяется не как текущий "снимок" данных, а как последовательность неизменяемых событий, которые привели к этому состоянию.
Ключевая идея: Вместо обновления записи в БД каждое изменение сохраняется как отдельное событие (например, OrderCreated, ItemAdded, PaymentProcessed). Текущее состояние воссоздается путем "проигрывания" (replaying) всех событий с начала.
Пример структуры событий и агрегата:
// События
record OrderCreated(String orderId, String customerId) {}
record ItemAdded(String orderId, String productId, int quantity) {}
record OrderShipped(String orderId, LocalDateTime shippedAt) {}
// Агрегат, который обрабатывает события
class OrderAggregate {
private String orderId;
private String status;
private List<OrderItem> items = new ArrayList<>();
// Метод для применения события и изменения состояния
void apply(OrderCreated event) {
this.orderId = event.orderId();
this.status = "CREATED";
}
void apply(ItemAdded event) {
this.items.add(new OrderItem(event.productId(), event.quantity()));
}
void apply(OrderShipped event) {
this.status = "SHIPPED";
}
}
// Восстановление состояния агрегата
OrderAggregate order = new OrderAggregate();
List<Event> history = eventStore.loadEvents(orderId);
history.forEach(event -> order.apply(event)); // Состояние восстановлено
Преимущества:
- Полный аудитлог: История всех изменений доступна по умолчанию.
- Временные запросы: Можно восстановить состояние системы на любой момент в прошлом.
- Гибкость: Новые представления данных (проекции) можно создать позже, обработав историю событий.
- Упрощение в сложных доменах: Хорошо сочетается с DDD и CQRS.
Недостатки и сложности:
- Сложность запросов: Получение текущего состояния требует обработки всех событий (решается с помощью проекций — Materialized Views).
- Миграция схемы событий: Изменение структуры старых событий требует осторожности (версионирование событий).
- Повышенные требования к хранилищу: Необходимо хранить все события.
Типичное применение: Финансовые системы, системы управления заказами, трекеры изменений, где критически важна полная история.
Ответ 18+ 🔞
Да ты послушай, что эти умники придумали, блядь! Event Sourcing, или, по-нашему, Хранение событий. Это ж надо было так мозги вывернуть!
Представь себе, сука: вместо того чтобы просто взять и переписать бумажку в базе данных, как нормальные люди, они каждое чихание записывают в отдельную графу. Создал заказ? Пишем событие OrderCreated. Добавил товар? ItemAdded. Отправил? OrderShipped. И так до скончания века, блядь!
А потом, если хочешь узнать, что там сейчас с заказом, тебе надо, блять, взять всю эту кипу бумажек и проиграть заново, как ёбаную кассету, с самого начала. Вот, смотри, как это выглядит в коде, тут всё честно:
// События — это святое, их не меняют, блядь
record OrderCreated(String orderId, String customerId) {}
record ItemAdded(String orderId, String productId, int quantity) {}
record OrderShipped(String orderId, LocalDateTime shippedAt) {}
// А это наш главный по тарелочкам — агрегат
class OrderAggregate {
private String orderId;
private String status;
private List<OrderItem> items = new ArrayList<>();
// Сюда события прилетают, и состояние меняется
void apply(OrderCreated event) {
this.orderId = event.orderId();
this.status = "CREATED";
}
void apply(ItemAdded event) {
this.items.add(new OrderItem(event.productId(), event.quantity()));
}
void apply(OrderShipped event) {
this.status = "SHIPPED";
}
}
// А вот магия восстановления, ёпта!
OrderAggregate order = new OrderAggregate();
List<Event> history = eventStore.loadEvents(orderId); // Достаём всю историю
history.forEach(event -> order.apply(event)); // И проигрываем, как старый диафильм
И что же мы, блядь, с этого имеем?
- Аудит как боженька: Кто, что, когда и куда — всё записано, спрятаться не получится. Идеально, если начальство ебёт мозг вопросами "а почему тут так?".
- Машина времени: Хочешь узнать, как было в прошлый вторник в 14:30? Пожалуйста, отмотай события до этого момента и посмотри. Красота, ёперный театр!
- Гибкость овердохуища: Позже придумал новый отчёт? Нет проблем, пробегись по всем старым событиям и сгенерируй его. История-то вся есть.
- Для сложных штук — то что надо: Когда бизнес-логика такая, что мозг скукоживается, этот подход часто выручает. Особенно если ещё и CQRS рядом приплести.
Но не всё так гладко, блядь:
- Запросы могут ебать мозг: Чтобы просто узнать текущую сумму заказа, надо всю историю пересчитать. Решается проекциями — это как заранее приготовленные сводки, чтобы не ебаться каждый раз.
- Схемы событий — боль: Захотел поле в событие добавить? Ой, да похуй, только вот со старыми данными теперь надо что-то делать. Версионируй, мигрируй, страдай, хуле.
- Места жрёт: Все события хранить — это не одну гигабайтную флешку захуярить. Дисков надо дохуя.
Где это всё, блядь, применяют? Да там, где история важнее всего: в банках, в бухгалтериях, в системах заказов — везде, где если что-то пошло не так, надо не орать "ой всё!", а иметь возможность пройти по шагам и найти, где именно накосячили. В общем, мощная штука, но не для всех, блядь. Если у тебя блог на WordPress, тебе это нахуй не сдалось.