Согласование небольших агрегатов и инвариантов в родительских / дочерних отношениях - PullRequest
0 голосов
/ 29 августа 2018

Во-первых, мое понимание / предположения агрегатов. * Агрегаты - это единственные доменные объекты, к которым можно получить прямой доступ. Если у агрегата есть дочерние элементы, доступ к ним должен осуществляться через агрегат. * Агрегаты могут иметь ссылки на другие агрегаты по их идентификатору. Это значит, что я могу загрузить Агрегат A через его репозиторий, получить ссылку на идентификатор для Агрегата B и загрузить B через репозиторий. * Большие агрегаты могут вызвать проблемы параллелизма, если корневая агрегат и дочерняя сущность обновляются независимо одновременно.

Для моего примера, у меня есть система членства, основанная на главах. Главы имеют членов. Пользователи должны иметь возможность вносить изменения в различные элементы одновременно, поэтому я должен сделать главу и элемент-член своими собственными агрегатами.

НО у нас есть правила, которые говорят

  • A) член должен принадлежать к главе
  • B) глава не может иметь двух членов с одинаковым именем и рождением дата.

A чувствует, что я должен иметь такой код

 var member = chapter.EnrollMember(memberInfo);

И этот код должен выдавать ошибку, если в главе уже есть член, который соответствует параметрам, переданным для B. Но если агрегат главы имеет только ссылки на id для других членов, как он должен получить эти элементы?

  • Перейти в репозиторий участника?
  • Переместить проверку имени участника из совокупности глав в службу домена?

ПРИМЕЧАНИЕ. Это гипотетическая ситуация. Я смотрю на то, как можно смоделировать эту ситуацию, а не на то, должна ли она быть смоделирована таким образом.

1 Ответ

0 голосов
/ 30 августа 2018

Проверка набора для больших наборов обычно нецелесообразна для обработки в домене. Если вы используете реляционную БД, вы можете защитить этот инвариант с помощью уникального ограничения.

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

Если политика уникальности членства почему-то чрезвычайно важна, должна быть строго согласованной, но слишком сложной, чтобы ее можно было смоделировать как уникальное ограничение, тогда вы могли бы смоделировать AR, который поддерживает только минимальное состояние для защиты инварианта, тогда как все остальные члены детали обрабатываются на отдельном AR. Например, name, birthdate и status члена могут быть смоделированы на сущности ChapterMember, которая находится в пределах Chapter, в то время как AR ChapterMemberProfile может содержать другие детали, которые не подлежат проверке набора.

//Enroll
var memberProfile = chapter.enrollMember(name, birthdate, avatarFilePath);

transaction {
    save(memberProfile);
    save(chapter);
}

//Change avatar for a given chapter
var memberProfile = find(chapterId, name, birthdate);
memberProfile.changeAvatar(avatarFilePath);

save(memberProfile);

//Disenroll (you could also modify memberProfile in the same transaction for this specific use case -- if needed)
chapter.disenrollMember(name, birthdate);

save(chapter);
...