DiC и SL в yii2

Обсуждаем, как правильно строить приложения
Ответить
Аватара пользователя
Cacatuidae
Сообщения: 65
Зарегистрирован: 2017.01.08, 17:39

DiC и SL в yii2

Сообщение Cacatuidae »

Подскажите, почему в yii2 есть SL (ServiceLocator), хотя на самом деле это полноценный DiC
Ведь он умеет создавать объект со всеми зависимостями через рефлексию класса
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: DiC и SL в yii2

Сообщение samdark »

А почему бы ему не быть?
Аватара пользователя
Cacatuidae
Сообщения: 65
Зарегистрирован: 2017.01.08, 17:39

Re: DiC и SL в yii2

Сообщение Cacatuidae »

Если не путаю, то паттерн SL не предусматривает такой возможности, а DiC как раз - да.
Мне непонятно почему он называется yii\di\ServiceLocator, а не yii\di\DiC например)
Вопрос задаю потому - вдруг чего ни так понял в этих двух паттернах
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: DiC и SL в yii2

Сообщение samdark »

SL не оговаривает такой возможности, но и не противоречит её наличию.
Аватара пользователя
Cacatuidae
Сообщения: 65
Зарегистрирован: 2017.01.08, 17:39

Re: DiC и SL в yii2

Сообщение Cacatuidae »

samdark писал(а): 2017.01.09, 00:25 SL не оговаривает такой возможности, но и не противоречит её наличию.
Получается так, что в данном случае в yii SL повторяет концепт DiC?
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DiC и SL в yii2

Сообщение ElisDN »

Cacatuidae писал(а): 2017.01.08, 17:54Ведь он умеет создавать объект со всеми зависимостями через рефлексию класса
Сам не может. yii\di\ServiceLocator вызывает именно yii\di\Container через метод Yii::createObject. А там уже контейнер парсит всё через рефлексию.
Последний раз редактировалось ElisDN 2017.01.09, 10:59, всего редактировалось 2 раза.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: DiC и SL в yii2

Сообщение samdark »

Так SL по сути не оговаривает, как именно достаются из контейнера объекты. Оговариваются две вещи: объекты там и достаются соответствующими методами, контейнер доступен глобально.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DiC и SL в yii2

Сообщение ElisDN »

Cacatuidae писал(а): 2017.01.09, 00:37Получается так, что в данном случае в yii SL повторяет концепт DiC?
В Yii1 был только SL с фабрикой Yii::createComponent. В Yii2 добавили DIC и поместили его вызов в метод Yii::createObject. В итоге имеем и DIC Yii::$container, и SL Yii::$app, работающий через DIC. В этом теперь и вся путаница: имеется два похожих инструмента, но с разными настройками.

Технической разницы между Yii::$app->get(...) и Yii::$container->get(...) почти нет. Только контейнер в Yii2 умеет сам парсить конструкторы. Но при желании можно "научить" и SL делать иньекции и превратить его в контейнер по примеру Pimple, определив все компоненты анонимками и прописав все иньекции вручную:

Код: Выделить всё

'components' => [
    'db' => [...],
    'session' => [...],
    'cart.session' => [...],
    'cart.storage.session' => function() {
        return new SessionStorage(
            Yii::app->get('cart.session'),
            'cartSessionKey'
        );
    },
    'cart' => function() {
        return new Cart(
            Yii::app->get('cart.storage.session')
        );
    },
],
Разница концепций только в манере использования. Если о нём внутри кода все знают глобально и из него дёргают объекты поштучно по требованию (а Yii::$app все так и испольуют), то это Service Locator. Если же его научить именно внедрять зависимости и использовать его локально только в самом верху (только в контроллере), чтобы о его присутствии ниже никто не догадывался, то это будет DI-контейнер.

Если все начнут дёргать Yii::$container->get(...) отовсюду по манере Yii::$app->get(...), то это будет использование контейнера как Service Locator.
Аватара пользователя
Cacatuidae
Сообщения: 65
Зарегистрирован: 2017.01.08, 17:39

Re: DiC и SL в yii2

Сообщение Cacatuidae »

Теперь понял.
Такой контроллер будет считаться за DiC

Код: Выделить всё

class CommandController extends Controller
{
    protected $parser;

    public function __construct($id, Module $module, Parsers $parser, array $config = [])
    {
        $this->parser = $parser;
        parent::__construct($id, $module, $config);
    }

    public function actionCommandRun()
    {
        var_dump($this->parser->canRun);
    }
}
Все остальное, включая настройки через конфигурацию - это SL.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: DiC и SL в yii2

Сообщение samdark »

Нет. DIC — это Dependency Container. Если его вызывать явно он, по сути становится Service Locator, но контейнером быть сам по себе не перестаёт. Что при этом происходит, так это нарушение инверсии зависимостей или Dependency Inversion. Inversion и Injection начинаются на одну и ту же букву, отсюда путаница на тему, что значит DI в конкретном случае.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: DiC и SL в yii2

Сообщение ElisDN »

Cacatuidae писал(а):Такой контроллер будет считаться за DiC
Это контроллер, в который из DIС прилетел $parser.

DIC - это Dependency Injection Container. Штука, которая инъектит зависимые объекты и настройки друг в друга.
Аватара пользователя
Cacatuidae
Сообщения: 65
Зарегистрирован: 2017.01.08, 17:39

Re: DiC и SL в yii2

Сообщение Cacatuidae »

Немного разобрался в этом. Вроде :)
Вдруг у кого есть возможность глянуть, такой подход https://github.com/Cacatuidae/yii2-sl-e ... er/IpRange
Не оверхед?
В файле https://github.com/Cacatuidae/yii2-sl-e ... tstrap.php настраиваются все зависимости для работы модуля
С помощьу этого, избавился везде в модуле от прямого создания объектов через new ClassName();
anton_z
Сообщения: 483
Зарегистрирован: 2017.01.15, 15:01

Re: DiC и SL в yii2

Сообщение anton_z »

В DI есть такое понятие - корень компоновки. Контейнер можно использовать явно только в этом самом корне. У каждого модуля может быть свой корень компоновки. Вы создали свой с помощью отдельного автозагружаемого компонента приложения. С точки зрения DI все нормально. Но вам придется помимо самого модуля подключать еще и компонент в конфигурации приложения.

По поводу кода на gihub. В контроллере вы используете uploadModel:

Код: Выделить всё


$fileAttribute = $this->uploadModel->getFileAttribute();
$this->uploadModel->{$fileAttribute} = UploadedFile::getInstance($this->uploadModel, $fileAttribute);
if($this->uploadModel->validate()) {
try {
     $this->uploadModel->saveFile();
У вас это одновременно сервис и форма. Нарушение SRP. Надо разделить. Сначала принять и валидировать форму, потом вызвать сервис для сохранения файла.
anton_z
Сообщения: 483
Зарегистрирован: 2017.01.15, 15:01

Re: DiC и SL в yii2

Сообщение anton_z »

Еще одно: статические фабрики - враги DI. Определите интерфейс и внедрите его в свой контроллер. Напишите реализацию, в которой будет данный вызов.

Код: Выделить всё


    public function actionMethod($method)
    {
        $params = ArrayHelper::merge(Yii::$app->request->getQueryParams(), Yii::$app->request->post());
        $object = MethodFactory::factory($method, ['params' => $params]);
        return $object->run();
    }

Аватара пользователя
Cacatuidae
Сообщения: 65
Зарегистрирован: 2017.01.08, 17:39

Re: DiC и SL в yii2

Сообщение Cacatuidae »

anton_z писал(а): 2017.01.15, 15:18 Но вам придется помимо самого модуля подключать еще и компонент в конфигурации приложения.
В Yii это штатная ситуация, когда подключается бустрап модуля.
anton_z писал(а): 2017.01.15, 15:18 У вас это одновременно сервис и форма. Нарушение SRP. Надо разделить. Сначала принять и валидировать форму, потом вызвать сервис для сохранения файла.
Нарушение даже если метод проксирует запрос на storage ?
https://github.com/Cacatuidae/yii2-sl-e ... el.php#L74

На счет фабрики согласен. Сейчас чтобы поменять фабрику, потребуется править код в контроллере.
anton_z
Сообщения: 483
Зарегистрирован: 2017.01.15, 15:01

Re: DiC и SL в yii2

Сообщение anton_z »

Cacatuidae писал(а): 2017.01.15, 17:49 В Yii это штатная ситуация, когда подключается бустрап модуля.
В zf2/3 и symfony в одном месте модуль/бандл подключил и все - там и bootstrap и компоновка. Но это лирика).
Cacatuidae писал(а): 2017.01.15, 17:49 Нарушение даже если метод проксирует запрос на storage ?
https://github.com/Cacatuidae/yii2-sl-e ... el.php#L74
Я думаю да. У вас форма - это сервис который валидирует данные И сохраняет файл в хранилище. Желательно чтобы таких явных "И" было как можно меньше. Это основной критерий проверки SRP.

В самом использовании формы как сервисе ничего плохого нет. Очень хорошо использовать для инжекции всяких сервисов/репозиториев для заполнения данными выпадающих списков и валидации.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: DiC и SL в yii2

Сообщение zelenin »

anton_z писал(а): 2017.01.15, 18:20
Cacatuidae писал(а): 2017.01.15, 17:49 В Yii это штатная ситуация, когда подключается бустрап модуля.
В zf2/3 и symfony в одном месте модуль/бандл подключил и все - там и bootstrap и компоновка.
немного разная концепция - в yii модули "ленивые" и являются скорее частью слоя контроллеров, т.к. инициализируются при реквесте. поэтому то, что нужно проинициализировтаь всегда выносится в bootstrap. В симфони же и зенде модули являются именно бутстрапом, и контроллерами отношения не имеет. (речь идет о Module.php, а не о модуле как логической единице)
Аватара пользователя
Cacatuidae
Сообщения: 65
Зарегистрирован: 2017.01.08, 17:39

Re: DiC и SL в yii2

Сообщение Cacatuidae »

anton_z писал(а): 2017.01.15, 18:20 Я думаю да. У вас форма - это сервис который валидирует данные И сохраняет файл в хранилище. Желательно чтобы таких явных "И" было как можно меньше. Это основной критерий проверки SRP.

В самом использовании формы как сервисе ничего плохого нет. Очень хорошо использовать для инжекции всяких сервисов/репозиториев для заполнения данными выпадающих списков и валидации.
Вынес статичную фабрику в класс https://github.com/Cacatuidae/yii2-sl-e ... actory.php
И отдельный контроллер для данного метода https://github.com/Cacatuidae/yii2-sl-e ... roller.php

А вот на счет разделение формы загрузки и сохранения файла, то тут я не понимаю как это реализовать правильно.
Ответить