Вопрос

Это практический вопрос по предметно-ориентированному дизайну:

Концептуально, я думаю, что получаю совокупные корни, пока не приступлю к их определению.

У меня есть сущность «Сотрудник», которая появилась как совокупный корень.В бизнесе, некоторый против сотрудников могут быть зарегистрированы нарушения, связанные с работой:

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

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

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

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

Это было полезно?

Решение

Проведя еще БОЛЬШЕ исследований, я думаю, что у меня есть ответ на мой вопрос.

Пол Стовелл дал слегка отредактированный ответ на аналогичный вопрос на Доска объявлений DDD.Замените «Клиент» на «Сотрудник» и «Заказ» на «Нарушение», и вы поймете идею.

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

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

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

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

РЕДАКТИРОВАТЬ** Единственная проблема в моей области в том, что нарушения не ведут себя.По сути, это записи о произошедшем событии.Пока не уверен в последствиях, которые это имеет.

Другие советы

Эрик Эван утверждает в своей книге: Доменно-ориентированный дизайн:Решение проблем, лежащих в основе программного обеспечения,

АГРЕГАТ — это кластер связанных объектов, которые мы рассматриваем как единое целое. с целью изменения данных.

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

  1. Эти объекты следует рассматривать как «единицу».
  2. С целью "изменения данных".

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

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

Итак, краткий ответ:

Я считаю, что «Сотрудник» и «Нарушение» принадлежат к двум отдельным агрегатам.Каждая из этих сущностей также имеет свои совокупные корни.Итак, вам нужно 2 репозитория:Репозиторий сотрудников и репозиторий нарушений.

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

var list = repository.FindAllViolationsByEmployee(someEmployee);

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

  • Сотрудник
  • СотрудникНарушения (назовите его «СотрудникВиолатионКард» или «СотрудникВиолатионРекордс»)

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

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

В этом я в целом согласен с Мошем.Однако имейте в виду понятие транзакций с точки зрения бизнеса.Поэтому я на самом деле понимаю «с целью изменения данных» как «с целью транзакции(й)».

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

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

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

Поэтому для этого варианта использования было бы справедливо сказать, что это транзакция, имеющая дело с нарушениями, и что корневая (или «основная») сущность — является нарушением.Тогда это будет ваш совокупный корень, на который вы будете ссылаться для этой конкретной бизнес-деятельности или бизнес-процесса.Но это не означает, что для другого действия или процесса вы не можете иметь совокупный корень «Сотрудник», например «процесс нового сотрудника».Если вы позаботитесь, не должно быть негативного влияния циклических ссылок или возможности проходить вашу модель предметной области несколькими способами.Однако я предупрежу, что управление этим должно рассматриваться и осуществляться вашей контроллерной частью вашего бизнес-домена или любым другим эквивалентом, который у вас есть.

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

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

Если использовать в качестве примера LINQ-To-SQL, DataContext будет контроллером, предоставляющим представление сущностей «Клиент» и «Заказ».Представление представляет собой недекларативный, ориентированный на платформу тип таблицы (грубый эквивалент репозитория).Обратите внимание, что представление сохраняет ссылку на свой родительский контроллер и часто проходит через контроллер, чтобы контролировать, как и когда представление материализуется.Таким образом, контроллер является вашим провайдером, отвечающим за картографирование, перевод, гидратацию объектов и т. д.Тогда моделью будут ваши POCO данных.Практически типичный шаблон MVC.

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

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

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
}

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

Мне было интересно, какой будет вывод?

«Нарушения» становятся корневым объектом.А на «нарушения» будет ссылаться корневая сущность «сотрудник».т.е. хранилище нарушений <-> хранилище сотрудников

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

Но является ли «поведение» критерием, позволяющим считать его корневой сущностью?Я так не думаю.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top