Почему Perl Редко Использует Ioc, Di И Волшебную Таблетку Kaiten::container

Думаю, многие понимают значение модных словечек «инверсия управления» (Ioc) и «внедрение зависимостей» (DI).

Если не очень интересно, на хабе было несколько статей на эту тему, очень информативно и доступно.

Методики отличные, но применить их в реальной жизни как-то не получилось.

Ниже под катом краткий обзор плачевного положения дел в Perl и самостоятельное «казалось бы» решение.

Итак, почему не получилось применить что-то в реальном коде.

На самом деле все вполне понятно — существующие модули, претендующие на реализацию DI, сложны для понимания и фантастически сложны в использовании, а в результате кода меньше, но больше.

И очень странно.

  
  
  
  
   

$c->add_service( Bread::Board::BlockInjection->new( name => 'authenticator', block => sub { my $service = shift; Authenticator->new( db_conn => $service->param('db_conn'), logger => $service->param('logger') ); }, dependencies => { db_conn => Bread::Board::Dependency->new( service_path => 'db_conn' ), logger => Bread::Board::Dependency->new( service_path => 'logger' ), } ) );

Пример из руководства Bread::Board, которое занимает 4 страницы!

$c = IOC::Slinky::Container->new( config => { container => { # constructor injection dbh => { _class => "DBI", _constructor => "connect", _constructor_args => [ "DBD:SQLite:dbname=/tmp/my.db", "user", "pass", { RaiseError => 1 }, ], }, # setter injection y2k => { _singleton => 0, _class => "DateTime", year => 2000, month => 1, day => 1, }, } } );

Пример IOC::Slinky::Container, это лучше, но все та же хрень, если вдуматься.



my $c = Peco::Container->new; $c->register('log_mode', O_APPEND); $c->register('log_file', '/var/log/my-app.log'); $c->register('log_fh', 'IO::File', ['log_file', 'log_mode']); $c->register('my_logger', 'My::Logger', ['log_fh']);

Пример Peco::Container — позиционируется как «контейнер Light Inversion of Control (IoC)».

Попробуйте взять последнюю строку и работать в обратном направлении.

Все еще понимаете, что происходит? ИМХО вся проблема в том, что эти реализации сложны, перегружены некоторыми фичами и как следствие трудноразрешимы, неудобны в использовании и могут превратить поддержку в ад. Все что нужно от DIc — это возможность поместить туда кусок кода и позже получить результат его выполнения.

Подставили пробел dbh и получили на выходе работающий обработчик.

Никакой магии, создания кода из файла конфигурации и прочих академических штучек.



my $kaiten_config = { examplep_config => { handler => sub { { RaiseError => 1 } }, probe => sub { 1 }, settings => { reusable => 1 }, }, ExampleP => { handler => sub { my $c = shift; my $conf = $c->get_by_name('examplep_config'); return DBI->connect( "dbi:ExampleP:", "", "", $conf ) or die $DBI::errstr; }, probe => sub { shift->ping() }, settings => { reusable => 1 } } }; my $container = Kaiten::Container->new( init => $kaiten_config ); my $dbh = $container->get_by_name('ExampleP');

Пример Kaiten::Container — простой, наглядный и эффективный.

Включены примеры и документация, вы можете получить их по адресу КПАН И github .

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

ПС.

Если модуль не хочет устанавливаться, сообщает что-то вроде

# Failed test 'use Kaiten::Container;' # at t/00-load.t line 6. # Tried to use 'Kaiten::Container'.

# Error: Argument "1.12_03" isn't numeric in numeric gt (>).



Присоединяйтесь к тем, кто жаждет патча Moo Здесь .

П.

П.

С.

И теперь в 3D! Поддерживается разрешение зависимостей.

Теги: #perl #IoC #di #инверсия управления #внедрение зависимостей #perl

Вместе с данным постом часто просматривают: