Как много логики я должен поместить свои методы хранилища при использовании шаблона хранилища? - PullRequest
9 голосов
/ 09 июня 2009

Я немного борюсь с репозиториями. Я использую C # и NHibernate. У меня вопрос: сколько должен делать мой репозиторий, прежде чем он вызовет сохранение или получение?

Например, у меня есть пользовательский класс, который является совокупным корнем. Я хочу вызвать метод с именем «register», который добавит пользователя и установит некоторые значения по умолчанию на основе бизнес-правил и создаст некоторые другие объекты, которые также являются частями корневого элемента «user» (т. Е. Адрес, группы и т. Д.). Должен ли я позвонить

userRepo.Register(newUser); 

что будет (игнорируя очевидные проблемы):

Regsiter(User newUser){
 newUser.SomeProp  = "Default Data";
 Group g= new Group;
 g.SomeProp2 = "Default Data";
 newUser.Groups.Add(g);
 Session.Save(g);
 Session.Save(newUser);
}

или я должен поставить регистр на бизнес-уровне и сделать это:

Regsiter(User newUser){
 newUser.SomeProp  = "Default Data";
 Group g= new Group;
 g.SomeProp2 = "Default Data";
 newUser.Groups.Add(g);
 userRepo.Register(newUser, g);// this does session.save on both objects.
}

Оба кажутся слегка неправильными.

Какой правильный подход?

изменить -------------------------------

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

Как правило, все говорят, поместите бизнес-правила на другой уровень. это имеет смысл, но я не уверен насчет вызовов данных для групп - поскольку группы не являются совокупным корнем, у них не должно быть своего собственного репозитория, так как мне их добавить и сохранить? В моем проекте добавление группы в коллекцию групп пользователя не создает группу автоматически в БД; мне также нужно вызвать session.save для объекта. так я помещаю это в пользовательский репозиторий как userRepo.SaveGroup (g)?

Если у меня есть createGroup () в другом слое, то ему нужно будет либо использовать свое собственное хранилище, либо пользователей. или я толстый?

Ответы [ 5 ]

6 голосов
/ 09 июня 2009

Лично я сохраняю шаблон хранилища вместо sprocs. Так что мой репозиторий будет иметь такие методы, как getById(int id), save(), add(DomainObject obj) и т. Д.

На бизнес-уровне у меня будет userManager.registerUser (строковое имя пользователя, / * params и т. Д. * /). Это создаст объект домена. Этот метод просто вызовет метод add() на уровне данных.

Короче говоря, бизнес-уровень - business-y, а уровень данных - data-y.

3 голосов
/ 09 июня 2009

Определите, где вы хотите, чтобы ваш метод Register, возможно, в классе UserServices. Вы можете делегировать создание объекта в UserFactory. В методе CreateNewUser () установите значения по умолчанию для пользователя и коллекции Groups. Затем вызовите UserRepository.Save (newUser), чтобы сохранить данные.

// UserServices class
public void Register(User newUser)
{
  // add custom registration stuff.
  _userRepository.Save(newUser);
}

// Application code
User user = UserFactory.CreateNewUser();
_userServices.Register(user);

// UserFactory
public User CreateNewUser()
{
  // all new user, group creation
}
3 голосов
/ 09 июня 2009

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

Если бы вы писали тест, чтобы проверить какую-то логику и не хотели попадать в базу данных, какие объекты вы должны будете макетировать? Обычно хранилище.

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

1 голос
/ 09 июня 2009

Из вашего примера кода я бы назвал метод Register сервисной операцией. Как операция сервиса, она будет принадлежать сервису или бизнес-компоненту, а не репозиторию. По словам Эванса (из известности DDD), хранилище представляет собой подобный коллекции интерфейс для сущностей, хранящихся в вашей базе данных. Общая идея заключается в том, что вы предоставляете базовый CRUD-подобный доступ к вашим сущностям через репозиторий, чтобы абстрагировать остальную часть кода от деталей доступа к данным более низкого уровня, таких как инструмент ORM.

Для вашего примера с Register ... ваш сервисный метод будет проверять ввод, создавать объект User, а затем вызывать ваш репозиторий, чтобы «добавить» ваш новый объект в «репозиторий» (который может быть базой данных ... но также может быть что-то еще ... что касается вашего домена, это не имеет значения ... это просто хранилище.)

0 голосов
/ 09 июня 2009

Я вижу две потенциальные проблемы "неправильности" (поскольку вы не указали, что, по вашему мнению, с ними не так).

  1. Если проблема связана с сохранением группы в методе регистрации пользователя или сохранением пользователя в методах группы, то вы должны разделить их на разные методы. (т.е. Register () будет вызывать RegisterGroup () или GetGroup ()

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

...