Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Профессионализм в пропаганде анти-паттерна Singleton? Идут лесом такие «профессионалы».
Тот магический вариант DI, которым хвастается статья, работает только, когда указан класс в качестве типа, а не интерфейс, что само по себе редкость.
App::bind('UserRepositoryInterface', 'DbUserRepository');
class Cache extends Facade {
protected static function getFacadeAccessor() { return 'cache'; }
}
App::container->get("cache")
Cache::shouldReceive('get');
Event::shouldReceive('fire');
Он является единственной точкой входа. Так, например если внутри фасада что-то изменится — использование его не изменится.
Тот магический вариант DI, которым хвастается статья, работает только, когда указан класс в качестве типа, а не интерфейс, что само по себе редкость.
А пример DI в статье, так вообще смешной, не понятно зачем он там %)
class A {
function __construct(B b=null) [
if (b === null) {
b = new B();
}
}
}
То есть по вашему главной фишкой di является автоматическое создание объектов и в этом вся суть? А то что мы можем быстро заменить имлементацию какого-то сервиса, от которого зависят наши, это так, бонус?
new MySuperClass или что-то в этом духе.
вы не путаете php и js? да, в php есть определенный уровень интроспекции, но даже там заменить имплементацию метода в рантайме довольно проблематично.
Даже более того, в java есть возможность подобного изменения кода в рантайме. но… Зачем?
Имея интерфейс A и сервис B зависящий от имплементации интерфейса A, мы сможем когда угодно подменить реализацию этого интерфейса A глобально для всего проекта. И к слову, подмена имплементации не происходит в рантайме, только во время разработки.
опять же как бы ни было тяжело или легко создавать объекты и передавать им нужные зависимости, с DiC это проще.
В динамическом языке вы сами понимаете это можно и без DI сделать
что вы подразумеваете под «четко выделенным di»? отдельный dependency injection фреймворк? Так есть, и даже не один.
По поводу классического di, где в конфигах прописываются только соответствия интерфейса реализации, а выбор зависимостей идет исключительно по тайп хинтам в создаваемых сервисах я пока не встречал,
<parameters>
<!-- ... -->
<parameter key="mailer.transport">sendmail</parameter>
</parameters>
<services>
<service id="mailer" class="Mailer">
<argument>%mailer.transport%</argument>
</service>
<service id="newsletter_manager" class="NewsletterManager">
<call method="setMailer">
<argument type="service" id="mailer" />
</call>
</service>
</services>
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(__DIR__));
$loader->load('services.xml');
// ...
$newsletterManager = $container->get('newsletter_manager');
Как правило динамичность сильно уменьшает понятность, сложно удержаться от перевода его в магию.
Вроде и аннотациями можно, но я их не очень люблю.
$foo = new Foo;
$foo->prop = 10;
do_something($foo); // явная передача экземпляра
var_dump($foo->prop); // очевидно, что здесь может быть не 10
Foo::prop = 10;
do_something(); // внутри делает Foo::prop = 20
var_dump(Foo:prop); // я ожидаю увидеть 10
Ларавельцы: зацените клевый фреймворк!
Толпа: там статика, фуууууу!
Ларавельцы: а что с ней не так?
Толпа: ее нельзя тестировать (куча ссылок на статьи)
Ларавельцы: так у нас же фасады! смотрите, как они клево тестируются! (пример)
Толпа: о, класс! и вправду круто!
Cache::put('foo', 'bar', $minutes);
do_something1();
do_something2();
do_something3();
do_something4();
var_dump(Cache::get('foo')); // baz
Cache::put до Cache::get.User::init();
$user = User::findById($id);
$userMeta = new UserMetа();
$userMeta->init();
$user = $userMeta->findById($id);
class UserMeta {
protected function getFields() {
/* какой то код */
return $fields;
}
}
public function setUserMeta(UserMetaInterface $userMeta) {}
User::init();
/* тут может быть вызов любой функции или любого статика */
$user = User::findById($id);
class User extends Eloquent {}
$user1 = User::findOrFail(1);
$user2 = User::findOrFail(1);
print_r($user1 === $user2); // false
Фреймворк вашего следующего веб-приложения