Как обновлять "большие" агрегаты в DDD

Как обновлять "большие" агрегаты в DDD
Как обновлять "большие" агрегаты в DDD - krisroller @ Unsplash

В моем домене есть часть, где у меня есть корневая сущность, с некоторыми полями, а затем некоторые другие сущности внутри этого агрегата, вот так:

class AggregateRootEntity {
   ... some fields ...
   Entity listOfInstancesOfThatEntity = [];
}

Учитывая, что агрегат может иметь, например, 200 экземпляров Entity в списке, как бы вы обновили агрегат с помощью хранилища? То есть, если я обновляю только элемент этого списка, мне нужно вызвать хранилище, как repository.update(AggregateRootEntity), но если я сделаю это так, то у меня не будет способа узнать, какая внутренняя сущность изменилась, поэтому мне нужно будет либо:

  1. Извлеките все внутренние сущности из хранилища и вычислите, какие из них изменились.
  2. Обновите их все.

Мне не нравится вариант 1, потому что это сделает код репозитория довольно сложным. Мне также не нравится вариант 2, потому что это сделает каждое обновление очень дорогим.

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

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

Есть альтернативный подход: не упорствовать без бизнес-контекста.

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

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

Однако они будут работать только до определенного момента и, возможно, уже специфичны для бизнес-логики, поскольку вы делаете их для конкретного случая.

Поэтому вместо этого есть одна альтернатива — сохраняться в контексте прецедента. Например, если вы в настоящее время пытаетесь отключить все кредитные карты клиента, вы можете просто запустить одну простую инструкцию SQL и покончить с этим. На самом деле вам не нужна отдельная модель данных в памяти, которую вы позже попытаетесь синхронизировать с базой данных.

Ключ в том, чтобы не раскрывать данные, а вместо этого раскрывать поведение. Если вам удастся это сделать (и я не говорю, что это легко), такого рода проблемы не появятся в первую очередь, поскольку вы всегда точно знаете, что пытается сделать пользователь, следовательно, у вас есть контекст с которые вы можете оптимизировать для конкретного случая.


LetsCodeIt, 27 декабря 2022 г., 05:34

Похожие посты

Детали модульного тестирования, в которых используется объект-значение, созданный фабрикойДилемма о наличии модели страны, провинции, города в отдельном агрегате или в одном агрегатеDDD - репозиторий vs антикоррупционный слойЯвляется ли извлечение интерфейса только для целей тестирования запахом кода?В многоуровневой архитектуре с взаимозаменяемыми поставщиками данных, как быть с деталями реализации, зависящими от поставщика?Дилемма о наличии модели страны, провинции, города в отдельном агрегате или в одном агрегатеDDD - модель и обеспечение соблюдения инвариантов для механизма рабочего процессаПоддержание ссылочной целостности между агрегированными корнямиDDD, агрегаты и коллекции с разбиением на страницы (конкретный случай)Как обновлять и сохранять агрегаты в DDD: ORM модели, репозитории и логика сохранения данных