ну и оно разные инстансы создает или один?
DI в DDD проектах
Re: DI в DDD проектах
Re: DI в DDD проектах
В Symfony логика такая:
В Symfony все сервисы shared по умолчанию. При автосоздании сервиса shared не отключается. Значит один инстанс....the subsystem is smart enough to automatically register a private service for the class...
Re: DI в DDD проектах
Небольшой пример реализации вышеописанного примера с PHP-DI:
Foo и Hoo будут созданы один раз и будут переиспользоваться
Код: Выделить всё
class Foo {
public function __construct()
{
echo "Foo", PHP_EOL;
}
}
class Bar {
public function __construct(Foo $foo)
{
}
}
class Hoo {
public function __construct(Foo $foo, Bar $bar)
{
}
}
$builder = new DI\ContainerBuilder();
$container = $builder->build();
$instance1 = $container->get(Hoo::class);
$instance2 = $container->get(Hoo::class);
var_dump($instance1 === $instance2);
Re: DI в DDD проектах
Значит в Symfony и PHP-DI даже с autowiring по умолчанию идёт один инстанс, что логично для контейнера $container->get(...). Для возврата новых инстансов нужно вручную отключать shared=false или объявлять фабрику.
В Yii, наоборот, для всего по умолчанию создаются новые инстансы, что логично для фабрики Yii::createObject(...). А общие сервисы нужно форсированно шарить через setSingleton(...).
В Yii, наоборот, для всего по умолчанию создаются новые инстансы, что логично для фабрики Yii::createObject(...). А общие сервисы нужно форсированно шарить через setSingleton(...).
Re: DI в DDD проектах
и тут они как раз поменялись местами - symfony/php-di выступают с позиции "быстрой разработки", а yii поступает более канонично и правильно (в ущерб rad).
Re: DI в DDD проектах
Ну если насчёт shared или не shared по умолчанию, то предпочитаю наоборот всё в shared.
Более склоняюсь к использованию контейнера именно как контейнера stateless сервисов-синглтонов c $container->get($id), а не как фабрику для клепания на лету новых инстансов по примеру Yii. В возврате новых инстансов для таких сервисов нет смысла. А если нужно клепать динамически инстансы как в фабрике, то и инъектим саму фабрику-синглтон и клепаем через $this->factory->create($params).
- slavcodev
- Сообщения: 3134
- Зарегистрирован: 2009.04.02, 21:42
- Откуда: Valencia
- Контактная информация:
Re: DI в DDD проектах
Да, я тоже считаю что "контейнер" для хранение stateless-сервисов а не для создания сервисов с разными состояниями.ElisDN писал(а): ↑2017.04.19, 16:20 Более склоняюсь к использованию контейнера именно как контейнера stateless сервисов-синглтонов c $container->get($id), а не как фабрику для клепания на лету новых инстансов по примеру Yii. В возврате новых инстансов для таких сервисов нет смысла. А если нужно клепать динамически инстансы как в фабрике, то и инъектим саму фабрику-синглтон и клепаем через $this->factory->create($params).
Жду Yii 3!
Re: DI в DDD проектах
А кто какой DI контейнер использует в проектах на Yii? и как вы его интегрируете c Yii (если используете сторонний)?
Re: DI в DDD проектах
Мы рефакторим проект на первом Yii, прикрутили zend-servicemanager от zf3. Очень простой и быстрый контейнер, построенный на фабриках. Поддерживает PSR. Зависимости запрашиваем в контроллере в первых строках экшенов и больше нигде. Это самая высокая точка для запроса зависимостей, которую предоставляет первый yii. Была бы какая-нибудь фабрика контроллеров, которую можно было бы подменить, инжектили бы через конструктор или методы экшенов.
Код: Выделить всё
/** @var Psr\ContainerInterface */
$cnt = \Yii::app()->getComponent('container');
$service = $cnt->get(SomeService::class);
Минусы - много фабрик писать, но зато они простые.
- slavcodev
- Сообщения: 3134
- Зарегистрирован: 2009.04.02, 21:42
- Откуда: Valencia
- Контактная информация:
Re: DI в DDD проектах
Я тоже Yii проект поддерживаю, зависимости инжектятся в экшн.
Код: Выделить всё
public function actionPut(SchedulePayment $command, LoadPayment $query, $paymentId)
{
$validator = new PaymentValidator();
$data = $this->loadIncomingData($validator);
$command->handle($paymentId, $data);
$payment = $query->loadPayment($paymentId);
if ($payment->isCompleted()) {
$this->sendLocationHeader(['paymentId' => $paymentId], 'get');
$this->sendResponse($payment, HttpStatus::REQUEST_CREATED);
} else {
$this->sendLocationHeader(['paymentId' => $paymentId], 'getQueued');
$this->sendResponse($payment, HttpStatus::REQUEST_ACCEPTED);
}
}
/**
* Returns params used to action binding.
* Uses union of services dependencies and $_GET.
*
* List of dependencies MUST be a priority and should be used first.
*
* {@inheritdoc}
*/
public function getActionParams()
{
return $this->getActionDependencies() + parent::getActionParams();
}
Жду Yii 3!