Каков наилучший способ повторного увлажнения совокупных корней и связанных с ними объектов в среде источников событий - PullRequest
0 голосов
/ 16 января 2020

Я видел информацию о регидратации агрегатных корней в SO, но я публикую этот вопрос, потому что я не нашел в SO никакой информации об этом в контексте среды, полученной из событий.

Имеет была найдена или разработана лучшая практика для повторного увлажнения агрегатных корней при работе на командной стороне приложения с использованием источника событий и шаблона CQRS

ИЛИ это все еще более «предпочтение» среди архитекторов?

Я прочитал несколько блогов и посмотрел несколько презентаций на вашей конференции, и мне кажется, что я получаю разные рекомендации в зависимости от того, кого я посещаю.

С одной стороны, я нашел информация, достаточно четко заявляющая, что разработчики должны создавать агрегаты, чтобы гидрировать себя, используя методы «применения» к событиям, полученным непосредственно из хранилища событий.

С другой стороны, я также видел в нескольких местах, где докладчики и блоггеры имеют рекомендуется регидрат агрегирование корней путем отправки запроса в сторону чтения приложения. Некоторые из них предложили создать специальные c проверочные «корзины» / проекции на стороне чтения, чтобы облегчить это.

Может ли кто-нибудь помочь мне указать верное направление при обнаружении единой передовой практики или если ответ в первую очередь зависит от проблем с производительностью или других проблем, о которых я не думаю?

Ответы [ 2 ]

2 голосов
/ 16 января 2020

Гидратирование агрегатов в рамках источника событий является хорошо понятой проблемой.

С одной стороны, я обнаружил информацию, в которой довольно четко указано, что разработчики должны создавать агрегаты для гидратации, используя методы «apply» для событий, полученных непосредственно из хранилища событий.

Это предписанный способ обращения с ним. Существуют различные способы достижения этой цели, но я бы рекомендовал хранить любую логику постоянства c (чтение или запись событий) за пределами вашего агрегата. Одним простым способом является предоставление конструктора, который принимает события домена, а затем применяет эти события.

С другой стороны, я также видел в нескольких местах, где докладчики и блоггеры рекомендовали регидрировать агрегатные корни, отправляя запрос стороне приложения для чтения. Некоторые предложили создать специальные c проверочные «корзины» / проекции на стороне чтения, чтобы облегчить это.

Вы можете использовать концепцию снимков как способ оптимизации ваших чтений. Это создаст запомненную версию вашего гидратированного агрегата. Вы можете загрузить этот снимок, а затем применить только те события, которые были созданы с момента создания снимка. В этом случае ваш Aggregate может определить конструктор, который принимает два параметра: существующее состояние (снимок) и любые оставшиеся события домена, которые затем могут быть применены к этому снимку.

Снимки являются просто оптимизацией и должны рассматриваться в качестве таких. Вы можете создать систему, которая не использует моментальные снимки, и применять их, когда производительность чтения становится узким местом.

С другой стороны, я также видел в нескольких местах, где докладчики и блоггеры рекомендовали регидрировать совокупные корни отправив запрос стороне чтения приложения

Снимки на самом деле не являются частью чтения приложения. Данные на стороне чтения существуют для удовлетворения вариантов использования в приложении. Они могут меняться в зависимости от требований, даже если базовый домен не меняется. Таким образом, вы вообще не должны использовать данные для чтения в вашем домене.

0 голосов
/ 24 января 2020

Источник сорсинга событий развил различные стили за эти годы. Я мог бы разделить все эти на две большие категории:

  • поток событий представляет одну сущность (совокупность в случае DDD)
  • один (разделенный) поток событий для (подсистема)

Когда вы работаете с одним потоком на (подсистему), вы не можете повторно обработать сторону записи на лету, это физически невозможно из-за количества событий в этом потоке. Следовательно, для получения текущего состояния объекта вы должны полагаться на проецируемую сторону чтения. Как следствие, эта сторона чтения должна быть полностью согласованной.

При выборе источника событий с ароматом DDD в сообществе существует твердое согласие относительно того, как это должно быть сделано. Состояние агрегата (не только root, но и всего агрегата) восстанавливается командой перед вызовом модели домена. Вы всегда восстанавливаете, используя события. Когда снимок включен, снимки также сохраняются как события в совокупном потоке снимков, поэтому вы читаете последнее и все события из версии снимка.

Относительно вещи Apply. Вам необходимо четко разделить функцию, которая добавляет новые события в список изменений (что вы собираетесь сохранить), и функции, которые изменяют агрегатное состояние при применении событий.

Первая функция - это функция с именем Apply, а второй часто называют When. Таким образом, вы вызываете функцию Apply в своем агрегатном коде для создания списка изменений. Функция When вызывается при восстановлении агрегатного состояния из событий при чтении потока, а также из функции Apply.

Вы можете найти упрощенный c пример агрегата, полученного из событий в моей книге репо: https://github.com/alexeyzimarev/ddd-book/blob/master/chapter13/src/Marketplace.Ads.Domain/ClassifiedAds/ClassifiedAd.cs

Например:

    public void Publish(UserId userId)
        => Apply(
            new V1.ClassifiedAdPublished
            {
                Id = Id,
                ApprovedBy = userId,
                OwnerId = OwnerId,
                PublishedAt = DateTimeOffset.Now
            }
        );

А для When:

    protected override void When(object @event)
    {
        switch (@event)
        {
            // more code here

            case V1.ClassifiedAdPublished e:
                ApprovedBy = UserId.FromGuid(e.ApprovedBy);
                State = ClassifiedAdState.Active;
                break;

            // and more here
         }
     }
...