Достаточно ли для объектов получить доступ к репозиториям?
Я только начал работать с DDD, так что, возможно, это глупый вопрос...
Можно ли получить доступ к репозиторию (через некоторый интерфейс IRepository) для получения значения во время выполнения? Например, я хочу принудительно выполнить выбор по умолчанию для свойства:
class Person {
private Company _employer;
public Company Employer {
get { return _employer; }
set {
if(value != null) {
_employer = value;
} else {
_employer = employerRepository.GetDefaultEmployer();
}
}
}
...
}
Мой вопрос заключается в том, что делать что-то подобное - это ужасное нарушение принципов DDD. И если это не так, моим следующим вопросом будет то, что это лучший способ предоставить репозиторий для использования? Должен ли он быть поставлен при создании объекта Person?
Спасибо,
Р
Ответы
Ответ 1
Это не ужасное нарушение DDD, это ужасное нарушение... ну... это просто ужасно (я говорю этот язык в щеку):).
Во-первых, ваша сущность становится зависимой от наличия репозитория... что не идеально.
В идеале вы хотите, чтобы ваш репозиторий создал Person, а затем назначил ему все, что ему нужно, чтобы быть эффективным в контексте текущего домена.
Итак, когда вам нужен Человек, вы отправите personRepository.GetPersonWithDefaultEmployer() и вернете человека, у которого есть работодатель по умолчанию. PersonRepository будет иметь зависимость от работодателяRepository и использовать его для заполнения человека до его возвращения.
PersonReposotory : IPersonRepository
{
private readonly IEmployerRepository employerRepository;
//use constructor injection to populate the EmployerRepository
public PersonRepository(IEmployerRepository employerRepository)
{
this.employerRepository = employerRepository;
}
public person GetPersonWithDefaultEmployer(int personId)
{
Person person = GetPerson(personId);
person.Employer = employerRepository.GetDefaultEmployer(personId);
return person;
}
}
Ответ 2
Тип ответа на ваш вопрос является стандартным: Это зависит.
Как правило, никогда не делайте этого. Держите свои сущности без ссылок на репозитории.
[надевая практическую шляпу] В некоторых крайне редких случаях, когда у вас есть очень, очень, очень веская причина для этого, добавьте большой комментарий, объясняющий, почему вы это делаете, и сделайте это: добавьте ссылку или используйте Double Отправьте, чтобы передать хранилище [без шапки]
Кроме того, если вы хотите следовать принципам DDD, настоятельно рекомендуется иметь доступ к эксперту по предметной области и итеративному процессу разработки (см. Эрик Эванс - то, что я узнал со времени появления книги).
Вместе с экспертом по домену вы должны определить ограничивающие контексты и, что наиболее важно, агрегаты и их совокупные корни, а также их сущности и объекты значений. Вначале идти по дороге DDD нелегко, но награды того стоят.
Несколько вещей относительно кода, который вы разместили:
Не рекомендуется иметь общедоступные сеттеры на ваших сущностях. Вместо этого используйте методы, которые лучше выражают намерение.
Если экземпляр лица создается без инициализации поля _employer, метод получения свойства Employer возвращает ноль. Если затем вы установите значение свойства Employer в значение null, следующий вызов метода получения вернет ненулевое значение. Вероятно, это неожиданно для пользователей вашего класса.
Вызывающий объект, устанавливающий значение Employer of Person (либо с помощью общедоступного установщика, либо с помощью общедоступного метода), должен знать точный экземпляр Company, который он хочет установить, даже если это экземпляр по умолчанию. Возможно, вызывающая сторона может иметь ссылку на хранилище.
В зависимости от вашего конкретного домена, Компания может быть ценным объектом. В этом случае вместо инициализации _employer с нулевым значением вы можете инициализировать его значением по умолчанию для объекта значения. Это может быть в том случае, если у вас очень мало компаний (1-2), и они неизменны и не имеют определенного поведения.
Ответ 3
Я думаю, что легко сказать, что сущность не должна знать о репозиториях, но трудно применить ее на практике. Особенно, когда агрегат получает большую коллекцию vo внутри него, мы должны реорганизовать его и делегировать операции, такие как добавить в какую-либо службу домена, которая фактически действует как репозиторий, чтобы избежать накладных расходов на загрузку всей коллекции в память,
Но я не думаю, что разумно позволять сущности знать о репозиториях. Если нам нужно, используйте вместо этого службы домена. Мы также должны учитывать, нарушает ли репозиторий принцип Single Responsibility - его следует рассматривать как Коллекция совокупных корней, а не нормальная factory.
Ответ 4
Это действительно то, что рекомендуется делать ddd?
И что, если у вас нет репозитория в памяти, а есть базовая база данных для вашего репозитория, и вы хотите получить 1000 человек со своим работодателем? Вы собираетесь сделать 1000 запросов через вызов работодателяRepository...?
Я бы использовал NHibernate или любой ORM, чтобы помочь реализовать personRepository. В NHibernate я буду использовать Hibernate Query рядом с этим: "from Person join fetch Employer", который будет загружать экземпляр "Employer" в каждом экземпляре "Person" с одним SQL-запросом.
Это нарушение DDD?
Ответ 5
Прежде всего, я думаю, что сама сущность и как собрать сущность на самом деле являются 2 обязанностями. Поэтому в идеале лучше распределить их по разному классу. Но это тоже зависит.