DDD, репозитории и ролевые интерфейсы

Я был бы очень признателен за мнения людей по указанной ниже проблеме дизайна.

У меня есть модель, в которой «Лицо» или «Бизнес» может быть поставщиком определенной «Услуги». Пример определения класса показан ниже:

IProvider
Guid Id

Человек: IProvider
Guid Id
string FirstName
string LastName

Компания: IProvider
Guid Id
string Name

Служба
Guid Id
IProvider поставщик

Поэтому я создал соответствующие концепции в своей области: «Человек», «Бизнес», «IProvider» и «Сервис». Я борюсь с тем, какие объекты создавать репозитории. В этом контексте «Сервис» является совокупным корнем и, следовательно, имеет собственное хранилище. «Бизнес» также является совокупным корнем в моем контексте, поскольку он будет иметь значение, даже если он не является поставщиком. «Лицо» будет создано в системе только в том случае, если оно «является Провайдером».

Могу ли я создать репозиторий для роли IProvider, который будет возвращать мне экземпляры «Person» и «Business»; мои проблемы с этим заключаются в том, что код может быстро стать довольно сложным, поскольку любая реализация должна будет смотреть на несколько таблиц и т.д., чтобы вернуть все разные типы IProvider. Такой подход потребует создания репозиториев для «Person» и «Business» и внедрения их в репозиторий «IProvider» для обеспечения необходимой функциональности, т. Е.

public class ProviderRepository : IProviderRepoistory
{
    public IBusinessRepository businessRepository {get; set; }
    public IPersonRepository personRepository {get; set; }

    public IProvider FindById(Guid Id){
        IProvider entity = businessRepository.FindById(Id);

        if(entity == null)
            entity = personRepository.FindById(Id);

        return entity;
    }
}

Другой оценкой будет создание репозиториев для сущностей «Лицо» и «Бизнес», которые реализуют интерфейс «IProvider», тем самым делая их доступными для участия в этой роли. т.е.

public class PersonRepository : IPersonRepository, IProviderRepository
{
    private ISession session;        

    public Person FindById(Guid Id){
        return session.Query<Person>().FirstOrDefault<Person>(x => x.Id == Id);
    }

    public IProvider FindById(Guid Id){
        return session.Query<Person>().FirstOrDefault<Person>(x => x.Id == Id && x.IsProvider == true);
    }
}

Затем я бы использовал механизм (то есть контейнер IoC), чтобы выбрать правильную конкретную реализацию IProviderRepository, когда это необходимо. Например, если я имею дело с поставщиком, который, как я знаю, является человеком, я могу получить реализацию PersonRepository.

Другой вариант - не реализовывать какие-либо репозитории IProvider, а просто придерживаться репозиториев «Person» и «Business» и использовать их по мере необходимости на уровне обслуживания?


person watsite    schedule 19.05.2011    source источник


Ответы (1)


Я думаю, вы слишком много думаете об этом и слишком рано пытаетесь оптимизировать.

Из всего, что вы здесь сказали, мне кажется, что Person и Business являются сущностями, но ни одна из них не является совокупностью (хотя, очевидно, мне может что-то не хватать в ваших обсуждениях с экспертами по предметной области). Мне кажется, что Провайдер - это совокупность.

Когда вы создаете ProviderRepository, вам не нужно внедрять репозитории для предприятий и лиц, b / c, если они не агрегаты, у них не должно быть собственных репозиториев. Вместо этого ProviderRepository должен использовать сеанс напрямую для извлечения того, что ему нужно, из любой схемы БД, которую вы придумали для составления рассматриваемых сущностей для данного запроса. Если вы правильно сопоставите наследование, вы можете выполнять запросы к базовому классу или интерфейсу.

person Paul    schedule 19.05.2011
comment
Спасибо за комментарии Пол. В моем случае бизнес-объект будет использоваться в системе, даже если он не является поставщиком. Например, пользователи домена будут вести бизнес-записи в системе, после чего часть из них может стать Провайдерами. - person watsite; 19.05.2011
comment
Я согласен с тем, что вы пытаетесь оптимизировать слишком рано. В моем проекте вполне вероятно, что источником данных может быть облачная служба, а не база данных для части домена, поэтому я не мог воспользоваться функцией nhibernates «is any» для автоматического поиска всех сущностей, реализующих данный интерфейс; поэтому я начал думать о том, как оптимизировать, где, как репозиторий IProvider может найти, откуда берутся данные, то есть какой тип проверять. - person watsite; 19.05.2011
comment
Достаточно справедливо, просто остерегайтесь ловушки ранней оптимизации. Что касается бизнес-объекта, используемого в системе, но не в качестве поставщика, рассмотрите ограниченные контексты как способ обдумать это. markhneedham.com/blog/2009/03/07/ddd -ограниченные-контексты - person Paul; 19.05.2011
comment
Спасибо за ссылку, Пол, я сделаю еще несколько исследований по BC. - person watsite; 19.05.2011