Интерфейс DI, нужно авторитетное мнение

t43

Новичок
Так у тебя в bindFor просто имя сервиса будет другое, нет?
bindFor используется что бы указать специальную связь (какой именно сервис передать), для определённого сервиса.

$di->getConfigurator()->getConfig('ICache')->bind('FileCache')->bindFor('b','MemCached');
по русски:
Для интерфейса ICache по умолчанию использовать класс FileCache(сервис), для сервиса b(есть зависимость ICache), использовать MemCached.
 

fixxxer

К.О.
Партнер клуба
ну я не просто так ссылку дал, там при похожем внешнем api код намного элегантнее (хоть и 8-летней давности)
 

t43

Новичок
ну я не просто так ссылку дал, там при похожем внешнем api код намного элегантнее (хоть и 8-летней давности)
Ну если не сложно, покажите где я реально туплю (не элегантно), со стороны это будет лучше видно.
Я серьёзно, без иронии.
 

fixxxer

К.О.
Партнер клуба
я дал пример, где то же самое написано красиво и элегантно.

в то, что делает портянка типа как у тебя getService без юнит тестов я вникать не хочу, извини
 

t43

Новичок
я дал пример, где то же самое написано красиво и элегантно.

в то, что делает портянка типа как у тебя getService без юнит тестов я вникать не хочу, извини
Вы походу про тот кусок что в посте сейчас пишите, я переписал это давно, ну да ладно.

https://github.com/BobrD/DependencyInjection
 

fixxxer

К.О.
Партнер клуба
При наличии юнит тестов все было бы понятно за одну минуту, а тут надо вникать. Вникать мне лень, потому просто дал пример, где точно знаю, что та же задача решена очень неплохо.
 

Вурдалак

Продвинутый новичок
bindFor используется что бы указать специальную связь (какой именно сервис передать), для определённого сервиса
Ну это понятно. Но ты так говоришь, словно сервис == класс. Это неправильно. Не нужно
PHP:
$di->get('a',['*cache'=>'MemCached '])
$di->get('a',['*cache'=>'FileCache'])
Нужно
PHP:
$di->get('a1')
$di->get('a2')
 

t43

Новичок
Ну это понятно. Но ты так говоришь, словно сервис == класс. Это неправильно. Не нужно
PHP:
//Получить сервис а испольльзовать MemCached как ICache
$di->get('a',['*cache'=>'MemCached '])
//Тут опять получить сервис а но с FileCache
$di->get('a',['*cache'=>'FileCache'])
Нужно
PHP:
//Получить сервис а1
$di->get('a1')
//Получить сервис а2
$di->get('a2')
a1 !== a2
Ой, что то я вас не понимаю)
завтра с утра ещё раз перечитаю и попробую въехать.
 
Последнее редактирование:

Вурдалак

Продвинутый новичок
Не понимаешь, потому что ты считаешь, что a1 и a2 — это имена классов. А это имена сервисов. Сервис — это не класс, это объект.

В общем, ни у тебя, ни у phemto нельзя получить сервис одного и того же класса с разными зависимостями, что является серьёзным минусом.

Писать
PHP:
$di->get('a',['*cache'=>'MemCached '])
не выход, потому что ты выносишь часть конфига в код и нарушаешь инкапсуляцию. Более того, в таком случае ты будешь вынужден передавать инстанс контейнера внутрь, чтобы уже там нарушить инкапсуляцию для следующей зависимости, которой тоже нужны особенные зависимости.

Посмотри лучше http://pimple.sensiolabs.org/, http://php-di.org/, http://symfony.com/doc/current/components/dependency_injection/index.html.
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
Аналог pimple я тут выкладывал, писал не зная про pimple. Сам этой реализацией и пользуюсь, чтобы не связываться с reflection, но, на самом деле, поюзав, не могу сказать, что это очень удобный подход. Из-за кучи требуемой оберточной писанины очень провоцирует на использование "как сервис локатора" - очень лениво писать все эти constructor functions, когда нужен всего-навсего вызов логгера в одном месте.

С другой стороны, yaml/xml-конфиги я в гробу видел, phemto хорош относительной лаконичностью в рамках php-кода. Именованные сервисы туда в принципе добавить легко (ввести named reuse lifecycle).
 

t43

Новичок
@Вурдалак pimple это service locator, у меня же DI. это немного разные вещи, хотя и то и то реализуют идею инверсии управления.

В общем, ни у тебя, ни у phemto нельзя получить сервис одного и того же класса с разными зависимостями
Ну а как DI угадает какие именно зависимости ты хочешь (если мы ему этого не сказали)?

Приведи пример api как ты это видишь.
 
Последнее редактирование:

t43

Новичок
Кто тебе такое сказал? У тебя путаница в понятиях.
http://habrahabr.ru/post/199296/
смотри комментарии

DI-контейнер же должен сам разбираться, кому какие аргументы конструктора вбить.
Если мы не используем интерфейсы т.е.
PHP:
class a
{
  
}

class b
{
    private $a;
    public function __construct( a $a)
    {
        $this->a = $a;
    }
}

$di->get('b');
DI сам определит, что нужно, сам создаст объект a, и вернёт уже готовый b.
ServiceLocator, так не умеет, ему нужно точно сказать что какой сервис хочет, вот и вся разница.
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
Комментарии на хабре - это да, это авторитетный источник.

DI от SL отличается вовсе не этим.
 

t43

Новичок
pimple не использует reflection, он не может сам определить что нужно инжектировать, а чем отличается DI от SL?
 

fixxxer

К.О.
Партнер клуба
Сервис-локатор:

PHP:
class C {

    protected $dep;

    public function __construct() {
        $this->dep = SL::get('dep');
    }

}

$c = new C;
DI:

PHP:
class C {

    protected $dep;

    public function __construct($dep) {
        $this->dep = $dep;
    }

}

$c = DI::get('C');
Каким именно образом задается конфигурация зависимостей для DI, не имеет никакого значения.
 

Вурдалак

Продвинутый новичок
Воу-воу, палехче. Основное отличие в использовании. Если ты инжектишь — это SL, если же ты вызываешь container->get() в минимуме мест (в идеале — в одном, например, при резолвинге контроллера), то тут уже DI (у всех классов зависимости будут инжектиться и никто ничего о контейнере, кроме самого фреймворка, не знает).

То, о чем мы тут говорим — это способы конфигурации DIC, это разные вещи.
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
Более того, DI прекрасно реализуется в языках, где нет никаких reflection - да и вообще классов с интерфейсами.
Например, pimple-подобная реализация есть в angularjs.
 
Сверху