Подтвердить что ты не робот

Что принадлежит совокупному корню

Это практический вопрос, связанный с управлением доменом:

Концептуально, я думаю, что получаю Aggregate, пока не пойду, чтобы определить его.

У меня есть объект Employee, который появился как корень Aggregate. В бизнесе некоторые сотрудники могут иметь связанные с ними Нарушения, связанные с работой:

Сотрудник ----- * Нарушения

Поскольку не все сотрудники подчиняются этому, я думаю, что Нарушения не будут частью Агрегата Рабочих, правильно?

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

Наконец, когда я добавляю "Нарушение", этот метод применяется к сущности Employee? Спасибо за помощь!

4b9b3361

Ответ 1

После еще большего исследования я думаю, что у меня есть ответ на мой вопрос.

Пол Стовелл слегка отредактировал ответ на аналогичный вопрос на DDD-сообщении. Замените "Заказчик" на "Сотрудник" и "Заказ" на "Нарушение", и вы получите эту идею.

Только потому, что ссылки клиентов не обязательно означает падение заказов в пределах совокупного корня клиента. Адреса клиентов могут, но заказы могут быть независимыми (для Например, у вас может быть служба, которая обрабатывает все новые заказы независимо от того, кто клиент. Приходится идти Заказчик → Заказы не имеют смысла в этот сценарий).

С точки зрения домена вы можете даже ставят под сомнение обоснованность этих ссылки (у Клиента есть ссылка на список ордеров). Как часто вы будете действительно нужны все заказы на клиент? В некоторых системах это делает смысл, но в других, один клиент может сделать много заказов. Скорее всего вам нужны заказы для клиента между диапазон дат или заказы для клиента которые еще не обработаны или заказы которые не были оплачены, и так далее. Сценарий, в котором вам понадобятся все из них могут быть относительно необычными. Однако гораздо более вероятно, что имея дело с Орденом, вы будете хотите получить информацию о клиенте. Итак, в код, Order.Customer.Name полезен, но Customer.Orders[0].LineItem.SKU - вероятно, не так полезен. Конечно, это полностью зависит от вашего бизнеса домен.

Другими словами, обновление клиента не имеет ничего общего с обновлением Заказов. И приказы, или нарушения в моем случае, могут мыслиться независимо от Клиентов/Сотрудников.

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

EDIT ** Морщина здесь, в моем Домене, заключается в том, что Нарушения не имеют никакого поведения. В основном это записи события, которое произошло. Еще не уверен, что имеет значение.

Ответ 2

В своей книге Эрик Эван утверждает, Проект, управляемый доменами: борьба с сложностью в сердце программного обеспечения,

AGGREGATE - это кластер связанных объектов, которые мы рассматриваем как единицу с целью изменения данных.

Здесь есть два важных момента:

  • Эти объекты следует рассматривать как "единицу".
  • Для целей "изменения данных".

Я считаю, что в вашем сценарии "Сотрудник и нарушение" не обязательно объединяются вместе, тогда как в примере Order and OrderItem они являются частью одного подразделения.

Еще одна важная вещь, которая важна при моделировании границ аггрегата, - есть ли у вас какие-либо инварианты в вашей совокупности. Инварианты - это бизнес-правила, которые должны быть действительными в совокупности. Например, что касается примера Order и OrderItem, вы можете иметь инвариант, который утверждает, что общая стоимость заказа должна быть меньше предопределенной суммы. В этом случае, в любое время, когда вы хотите добавить OrderItem в Order, этот инвариант должен быть принудительно соблюден, чтобы убедиться, что ваш ордер действителен. Однако в вашей проблеме я не вижу никаких инвариантов между вашими сущностями: "Сотрудник" и "Нарушение".

Короткий ответ:

Я считаю, что каждый сотрудник и Нарушение принадлежат к двум отдельным агрегатам. Каждый из этих сущностей также является их собственными совокупными корнями. Поэтому вам нужны 2 репозитория: EmployeeRepository и ViolationRepository.

Я также считаю, что у вас должна быть однонаправленная ассоциация от Нарушения Сотруднику. Таким образом, каждый объект "Нарушение" знает, кому он принадлежит. Но если вы хотите получить список всех Нарушений для конкретного Сотрудника, вы можете спросить ViolationRepository:

var list = repository.FindAllViolationsByEmployee(someEmployee);

Ответ 3

Вы говорите, что у вас есть сущность сотрудника и нарушения, и каждое нарушение не имеет никакого поведения. Из того, что я могу прочитать выше, мне кажется, что у вас могут быть два совокупных корня:

  • Сотрудник
  • EmployeeViolations (назовите это EmployeeViolationCard или EmployeeViolationRecords)

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

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

Ответ 4

Я вообще согласен с Мошем на этом. Однако имейте в виду понятие транзакций в деловой точке зрения. Поэтому я фактически беру "для целей изменения данных", что означает "для транзакции (транзакций)".

Репозитории - это виды модели домена. В среде домена эти "представления" действительно поддерживают или представляют бизнес-функцию или возможность - транзакцию. Дело в том, что у Работника может быть одно или несколько нарушений, и если да, это аспекты транзакции (транзакций) в определенный момент времени. Рассмотрите свои варианты использования.

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

Сотрудник < ---- совершает -------, совершенный ---- > Нарушение

Итак, для этого случая использования было бы справедливо сказать, что это транзакция, связанная с нарушениями, и что корневой или первичный сущность - это Нарушение. Это будет ваш общий корень, который вы бы указали на эту конкретную бизнес-деятельность или бизнес-процесс. Но это не означает, что для другого действия или процесса у вас не может быть root-агрегат Employee, например, "новый процесс сотрудника". Если вы позаботитесь, не должно быть отрицательного воздействия циклических ссылок или быть способным пересечь вашу модель домена несколькими способами. Однако я буду предупреждать, что управление этим должно быть рассмотрено и обработано вашей частью контроллера вашего бизнес-домена или любым другим эквивалентом, который у вас есть.

Помимо этого: размышление в терминах шаблонов (т.е. MVC), репозиторий представляет собой представление, объекты домена являются моделью, и поэтому также следует использовать некоторую форму шаблона контроллера. Как правило, контроллер объявляет конкретную реализацию и доступ к репозиториям (коллекции совокупных корней).

В мире доступа к данным...

Используя LINQ-To-SQL в качестве примера, DataContext будет контроллером, отображающим представление объектов Customer и Order. Представление представляет собой не декларативный, ориентированный на платформу тип таблицы (грубый эквивалент репозиторию). Обратите внимание, что представление сохраняет ссылку на его родительский контроллер и часто проходит через контроллер, чтобы контролировать, как/когда представление становится материализованным. Таким образом, контроллер является вашим провайдером, заботясь о картировании, переводе, гидратации объектов и т.д. Модель - это ваши данные POCOs. Довольно типичный шаблон MVC.

Используя N/Hibernate в качестве примера, ISession будет контроллером, отображающим представление объектов Customer и Order посредством сеанса. Enableerable (строковый запрос) или session.Get(идентификатор объекта) или session.CreateCriteria(typeof (Заказчик)). Список()

В мире бизнес-логики...

Customer { /*...*/ }

Employee { /*...*/ }

Repository<T> : IRepository<T>
              , IEnumerable<T>
              //, IQueryable<T>, IQueryProvider //optional

{ /**/ }

BusinessController {
 Repository<Customer>  Customers { get{ /*...*/ }} //aggregate root
 Repository<Order> Orders { get{ /*...*/ }} // aggregate root
}

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

Ответ 5

Мне было интересно, что такое заключение?

"Нарушения" становятся корневой сущностью. И "нарушения" будут ссылаться на корневую сущность "employee". т.е. репозиторий репозитория и lt; → репозиторий сотрудников

Но вы не согласны с тем, что делаете нарушения корневой сущностью, потому что у нее нет никакого поведения.

Но является ли "поведение" критерием для квалификации как корневой сущности? Я так не думаю.

Ответ 6

немного ортогональный вопрос, чтобы проверить понимание здесь, возвращаясь к порядку... Пример OrderItem, в системе может быть модуль аналитики, который хочет напрямую изучить OrderItems, т.е. получить все orderItems для определенного продукта или весь порядок больше, чем какое-либо заданное значение и т.д., имеет ли много таких данных и управляет "агрегированным корнем" до крайности, можем ли мы утверждать, что OrderItem - это другой собственный совокупный корень?

Ответ 7

Это зависит. Изменяет ли какое-либо изменение/добавление/удаление изменения в какой-либо части сотрудника - например, вы храните счетчик нарушений или количество нарушений в течение 3 лет против сотрудника?