Doctrine2 Best Practice, Должны ли организации использовать Услуги? - PullRequest
3 голосов
/ 16 декабря 2010

Я задал похожий вопрос некоторое время назад: Используя шаблон сопоставления данных, должны ли сущности (доменные объекты) знать о преобразователе? Тем не менее, он был общим и Мне действительно интересноо том, как выполнить несколько вещей с помощью Doctrine2, в частности .

Вот простой пример модели: каждая Thing может иметь Vote из User, User может разыграть болееодин Vote, но учитывается только последний Vote.Поскольку другие данные (Msssage и т. Д.) Связаны с Vote, когда помещается вторая Vote, исходная Vote не может быть просто обновлена, ее необходимо заменить.

В настоящее время Thing имеет эту функцию:

public function addVote($vote)
{
  $vote->entity = $this;
}

И Vote заботится о настройке отношений:

public function setThing(Model_Thing $thing)
{
  $this->thing = $thing;
  $thing->votes[] = $this;
} 

Мне кажется, что обеспечение только User имеетпоследний Vote считается тем, что Thing должен обеспечить, а не каким-то служебным слоем .

Таким образом, чтобы сохранить это в модели, новая функция Thing:

public function addVote($vote)
{
  foreach($this->votes as $v){
    if($v->user === $vote->user){
      //remove vote
    }
  }
  $vote->entity = $this;
}

Итак, как мне удалить Vote из модели предметной области? Должен ли я расслабиться Vote::setThing(), чтобы принять NULL?Должен ли я задействовать какой-либо уровень обслуживания, который Thing может использовать для удаления голоса?Как только голоса начнут накапливаться, это foreach будет медленным - следует ли использовать служебный слой, чтобы Thing мог искать Vote, не загружая всю коллекцию?

I 'я определенно склоняюсь к использованию легкого сервисного слоя;Однако, Есть ли лучший способ справиться с этим типом вещей с помощью Doctrine2, или я иду в правильном направлении?

Ответы [ 2 ]

7 голосов
/ 17 декабря 2010

Я голосую за сервисный слой. Я часто боролся с попытками добавить как можно больше логики на саму сущность и просто разочаровывался. Без доступа к EntityManager вы просто не сможете выполнять логику запросов, и вы обнаружите, что используете много операций O (n) или ленивую загрузку целых наборов отношений, когда вам нужно всего несколько записей (что супер хромает по сравнению со всеми преимуществами, которые предлагает DQL).

Если вам нужна помощь в преодолении идеи о том, что модель анемического домена всегда является анти-паттерном, см. эту презентацию Мэтью Вейера О'Пинни или этот вопрос .

И хотя я мог неправильно истолковывать терминологию, я не совсем убежден, что сущности должны быть единственными объектами, разрешенными в вашей доменной модели. Я бы легко предположил, что сумма объектов Entity и их Сервисов составляет Модель. Я думаю, что анти-паттерн возникает, когда вы заканчиваете тем, что пишете сервисный слой, который мало обращает внимания на разделение интересов.

Я часто заигрывал с мыслью о том, чтобы все мои объекты-сущности передавали некоторые методы на сервисный уровень:

public function addVote($vote)
{
   $this->_service->addVoteToThing($vote, $thing);
}

Однако, поскольку в Doctrine нет какой-либо системы событий обратного вызова при гидратации объекта, я не нашел элегантного способа внедрить объект службы.

6 голосов
/ 20 декабря 2010

Я бы посоветовал поместить всю логику запроса в EntityRepository, а затем сделать из нее интерфейс вроде:

class BlogPostRepository extends EntityRepository implements IBlogPostRepository {}

таким образом вы можете использовать интерфейс в своих юнит-тестах для сервисных объектов, и никакой зависимости от EntityManager не требуется.

...