Несколько замечаний по поводу ответа @ RPM1984 ...
Однако в вашем вопросе у вас есть IRepository в доменном проекте, я бы поставил это в вашей сборке репозиториев.
Хотя неважно, куда Вы помещаете вещи физически, важно помнить, что абстракции репозиториев являются частью домена.
У нас также есть сервисный уровень, который является посредником между пользовательским интерфейсом.(Контроллеры) и репозиторий.Это позволяет централизованно размещать логику, не принадлежащую репозиторию, - такие как Paging and Validation.
Я считаю, что не стоит создавать сервис только для подкачки и проверки.Еще хуже, если он создан искусственно - просто потому, что «все проходит через сервисы» и «таким образом, вам не нужно ссылаться на репозитории из пользовательского интерфейса».По возможности следует избегать служб приложений.
Для проверки входных данных - уже есть хороший момент для этого "из коробки".Если вы используете asp.net mvc, подумайте о том, чтобы следующий шаблон MVVM и инфраструктура предоставили достаточно хороших способов для проверки ваших моделей входного представления.
Если вам нужно взаимодействие между несколькими агрегатными корнями (это признак того, что вы можете отсутствовать)новый агрегатный корень) - напишите домен сервис.
Вы, похоже, на правильном пути, но, похоже, хотите пойти "DDD-All-The-Way"Рассматривали ли вы возможность применения шаблона «Единица работы» для управления несколькими репозиториями, использующими один и тот же контекст?
Я думаю, что также следует избегать единицы работы. Вот почему :
Еще один пример, UoW - это действительно проблема инфраструктуры, зачем вы вносите это в домен ?.Если у вас правильные совокупные границы, вам не нужна единица работы.
Репозитории не принадлежат домену.Репозитории - это постоянство (то есть инфраструктура), домены - это бизнес.
Хранилища получили смешанную ответственность.С одной стороны - бизнесу все равно, как и где будут храниться данные.Из других - знание того, что покупатели могут быть найдены по содержанию их корзины покупок (упрощенный пример).Следовательно - я утверждаю, что только абстракций должны быть частью домена.Кроме того - я против прямого использования репозиториев из доменной модели, потому что оно должно быть невежественным.
Сервисный уровень обеспечивает центральную точку для «проверки бизнеса».
Прикладные услуги в основном это просто фасадов .И каждый фасад плох, если сложность добавляет сложностей, которые он решает.
Вот плохой фасад:
public int incrementInteger(int val){
return val++;
}
Службы приложений не должны содержать бизнес-правила.В этом и заключается смысл доменного проектирования - вездесущий язык и изолированный код, который отражает бизнес максимально просто и просто.
MVC хорош для простой проверки, но не для сложных бизнес-правил (представьте шаблон спецификации).
И вот для чего это нужно.Например, чтобы проверить, может ли опубликованное значение быть проанализировано как datetime, которое должно быть передано в качестве аргумента в домен.Я называю это проверкой пользовательского интерфейса.Есть многих из них .
RE UoW - я заинтригован этим предложением, но не могли бы вы уточнить?UoW - это действительно проблема, связанная с инфраструктурой, но, опять же, это в моем хранилище / уровне данных, а не в моей области.Все, что у меня есть в домене - это бизнес-объекты / спецификации.
Шаблон единицы работы побуждает нас ослаблять совокупные корневые границы.В основном - это позволяет нам выполнять транзакции по нескольким корням.Несмотря на то, что он находится за пределами домена, он все же оказывает неявное влияние на решения, принимаемые нами в области и моделировании.Довольно часто это приводит к так называемой модели анемичной области.
Еще одна вещь: слоев! = Уровни .
Еще одно замечание, которое я хотел бы отметить, это то, что DDD - это руководство, а не «все-и-все-все-конец».
Да, но это не должно служить оправданием.:)
Другая причина для нашего уровня обслуживания заключается в том, что у нас есть веб-API.Мы НЕ хотим, чтобы наш веб-API вызывал в наши репозитории, нам нужен хороший свободный интерфейс, через который могут обращаться как веб-приложение, так и API.
Если нет ничего более, чем получить root и вызвать его метод- Сервис просто обернуть, что не нужно.Поэтому - я подозреваю, что ваша настоящая проблема заключается в отсутствии этой изоляции, следовательно - необходимо организовать взаимодействие между корнями.
Здесь Вы можете увидеть некоторые детали моего текущего подхода.
Еще одна БОЛЬШАЯ причина для нашего уровня обслуживания - наши репозитории возвращают IQueryable, поэтому они не имеют никакой логики.Наш Сервисный Уровень проецирует выражения linq в бетоны
Это не звучит правильно.Та же проблема - отсутствие изоляции.
В этом случае - хранилища недостаточно абстрактны для сохранения.У них должна быть логика - та, которая связана с настойчивостью.Знание, как хранить и извлекать данные.Делегирование того, что «где-то снаружи» разрушает всю точку хранилищ и все, что останется - точку расширения для проверки доступа к данным для тестирования (что неплохо).
Другое дело, если хранилища возвращают необработанныеIQueryable
, который автоматически связывает уровень обслуживания с неизвестным (!) Провайдером LINQ.
И менее плохая вещь (это может даже не понадобиться) - из-за высокой связи это может бытьдовольно трудно переключить постоянство на другую технологию.
Не забывайте, что речь идет о технических проблемах.Эти вещи не имеют ничего общего с design , они просто делают это возможным.
Если вы не используете сервисный уровень, как бы вы (например,) восстановить список заказов на товар?Вам понадобится метод в вашем репозитории под названием «GetOrdersForProduct», который я не считаю хорошим дизайном.Ваш интерфейс репозитория становится огромным, его невозможно поддерживать.Мы используем очень общий репозиторий (Найти, Добавить, Удалить и т. Д.).Эти методы отрабатывают объект, установленный в нашей модели.Универсальность / мощность запросов передаются на уровень обслуживания
Этот хитрый.Я просто оставлю хорошая ссылка .
С неизвестным провайдером, я имею в виду - Вы действительно не можете сейчас узнать, что находится под уровнем обслуживания.Это может быть Linq для объектов, это может быть Linq для xml, Linq для sql, NHIbernate.Linq и множество других реализаций провайдера.Плохая вещь - вы не можете знать, что поддерживается.
Это будет прекрасно работать, если это Linq для объектов, и потерпит неудачу, если его нужно преобразовать в sql:
customers.Where(c=>{var pickItUp=c.IsWhatever; return pickItUp;});