Во время обучения у @ tereško’s ответ о том, как должна быть структурирована модель, я не могу найти лучший способ связи между службами. Я также нашел этот Ответ, который похож на ситуацию, с которой я имею дело, но пример отлично подходит для демонстрации. Итак, в этом смысле, как я могу получить службу распознавания внутри службы блога, например, когда служба имеет доступ только к объектам фабрики домена и маппера. Я посылаю это от контроллера? Или мне тоже нужно отправить сервисную фабрику?
Обновить:
Я не привел пример, поскольку упомянул, что второй ответ Терешко очень похож на то, что я пытаюсь достичь. Я пытаюсь создать BlogService, который, например, хранит сообщение. Чтобы сохранить автора сообщения, я пытаюсь получить (его названный) сервис распознавания, чтобы получить зарегистрированного пользователя (который, очевидно, является автором сообщения).
class BlogService
{
public function storePost($title, $content)
{
$post = $this->domainFactory->build('Post');
$mapper = $this->mapperFactory->build('Post');
$post->setTitle($title);
$post->setContent($content);
$post->setAuthor( /* get logged in user */ );
$mapper->save($post);
}
}
Так что в основном ваш вопрос «Как поделиться объектом домена из службы распознавания с какой-либо службой контента?». Я действительно думал об этом в течение некоторого времени.
На мой взгляд, здесь есть 4 варианта. Два дерьмовых, один хороший и один промежуточный:
Ранее упоминался подход «Пройди сервисную фабрику».
Это наиболее наивное решение, потому что в реальной ситуации вы получите неконтролируемый рост графа объектов — сервис, содержащий сервисы, содержащие сервисы. до тошноты.
Это неустойчиво, но быстро.
Измените службу распознавания таким образом, чтобы она Account
экземпляр в контроллер, который затем, в свою очередь, передает другим службам.
По сути, вы бы создали намеренную утечку между слоями, чтобы минимизировать сложность. Вы могли бы назвать это «архитектурной денормализацией».
Это хак и плохая архитектура.
Используйте DI-контейнер для совместного использования объектов домена (и даже сопоставителей) между службами.
Этот способ более сложен в предыдущих двух, но он также позволит вам полностью избавиться от фабрик внутри ваших сервисов.
Лучший вариант, но требует дополнительных навыков и кода.
Используйте фабрику объектов вашего домена для создания экземпляра Account
(и все остальные или выбранные) только один раз.
Вроде как в этот пост, но для доменных объектов. Конечно, вам потребуется какой-то способ обойти «кеш», потому что большая группа доменных объектов потребует возможности инициироваться более одного раза. Таким образом — необходимость в некоторой конфигурации.
Это сложное промежуточное решение, но оно позволяет вам хранить знакомый API в сервисах.
Я сам в настоящее время использую вариант 2. Причина в том, что у меня нет контейнера DI, который я мог бы использовать (и я подумал о «варианте 4» только 5 минут назад). Большинство из того, что вы видите под описанием «Контейнер PHP DI», на самом деле представляют собой различные сервисные локаторы (в любом случае вам лучше работать с кучей фабрик).
Если вы хотите пойти с DI-контейнером, моя поддержка идет в Auryn.
И причина, по которой я сам этим не пользуюсь, заключается в том, что я действительно высокомерен, я хочу создать свой собственный DI-контейнер.
Вместо того чтобы писать это:
$post->setAuthor($user);
Вы должны написать что-то вроде этого:
$post->setAuthorId($user->getId());
.. по двум причинам:
Post
Например, чтобы управлять своими отношениями с другими лицами. Вот для чего у вас есть сервис.Account
Например, вы бы в конечном итоге извлечь идентификатор в любом случае. Так что вы будете нарушать Закон Деметры никакой практической пользы.Я предполагаю, что domainFactory и mapperFactory являются экземплярами шаблона Abstract Factory.
Поскольку ваш BlogService уже требует этих двух абстрактных фабрик, почему бы не иметь третью, ServiceFactory.
Ответственность за этот объект будет заключаться в создании (предпочтительно абстрактных) продуктов, услуг.