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

WebDriver не является потокобезопасным. Я могу сослаться на Selenium FAQ

Q: Является ли WebDriver поточно-ориентированным?
A: WebDriver не поточно-ориентирован. Сказав это, если вы можете сериализовать доступ к базовому экземпляру драйвера, вы можете поделиться ссылкой более чем в одном потоке. Это не рекомендуется. С другой стороны, вы можете / можете / создать один экземпляр WebDriver для каждого потока.

blockquote>

Не имеет значения, используется ли ваше решение в больших или малых проектах. Если вы хотите масштабировать свое решение, вы всегда можете использовать сетку Selenium для параллельного выполнения. Локальные объекты WebDriver не будут вашей проблемой. Заполнение памяти съедая экземпляры Chrome будет вашей проблемой.

32
задан jlembke 9 January 2012 в 17:28
поделиться

4 ответа

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

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

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

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

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

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

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

25
ответ дан 27 November 2019 в 20:56
поделиться

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

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

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

Но является ли «поведение» критерием для квалификации в качестве корневого объекта? Я так не думаю.

0
ответ дан 27 November 2019 в 20:56
поделиться

Эрик Эван утверждает в своей книге Domain-Driven Design: Tackling the Complexity in the Heart of Software ,

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

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

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

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

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

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

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

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

var list = repository.FindAllViolationsByEmployee(someEmployee);
21
ответ дан 27 November 2019 в 20:56
поделиться

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

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

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

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

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

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

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

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

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

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

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
}

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

1
ответ дан 27 November 2019 в 20:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: