Доктрина2 лучшая практика, должны ли организации пользоваться услугами?
-
11-10-2019 - |
Вопрос
Я задал аналогичный вопрос некоторое время назад: Используя шаблон Mapper Data, должны ли объекты (объекты домена) знать о Mapper? Однако это было общее и Меня очень интересно, как сделать несколько вещей с 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
не загружая всю коллекцию?
Я определенно склоняюсь к использованию легкого сервисного слоя; Однако, Есть ли лучший способ справиться с этим типом вещей с Doctrine2, или я движусь в правильном направлении?
Решение
Я голосую за уровень обслуживания. Я часто боролся с попыткой добавить столько логики на саму сущность, и просто расстроился. Без доступа к EntityManager вы просто не можете выполнить логику запросов, и вы обнаружите, что используете много операций O (n) или ленивые наборы отношений, когда вам нужно только несколько записей (что супер хромым по сравнению со всеми преимуществами, которые предлагает DQL).
Если вам нужна помощь, чтобы преодолеть идею, что модель анемичной области всегда является анти-паттерном, посмотрите это презентация Мэтью Вейер О'Финни или этот вопрос.
И хотя я мог бы неверно истолковывать терминологию, я не совсем убежден, что сущности должны быть единственными объектами, разрешенными в вашей модели домена. Я бы легко рассмотрел, что сумма объектов объектов и их услуг составляет модель. Я думаю, что анти-паттерн возникает, когда вы в конечном итоге пишете сервисный слой, который практически не обращает внимания на разделение проблем.
Я часто флиртовал с идеей, чтобы все мои объекты были прокси -серверы для уровня обслуживания:
public function addVote($vote)
{
$this->_service->addVoteToThing($vote, $thing);
}
Однако, поскольку доктрина не имеет никакой системы событий обратного вызова при гидратации объектов, я не нашел элегантного способа внедрения объекта обслуживания.
Другие советы
Мой совет - поместить всю логику запросов в EntityRepository, а затем сделать интерфейс из него вроде:
class BlogPostRepository extends EntityRepository implements IBlogPostRepository {}
Таким образом, вы можете использовать интерфейс в ваших единичных тестах для объектов службы, и никакой зависимости от EntityManager не требуется.