📜 ⬆️ ⬇️

Why IoC, DI and Kaiten :: Container Magic Pill are so rarely used in Perl

I think many understand the significance of Inversion of Control (Ioc) and Dependency Injection (DI) buzzwords. If not very, but interesting - on Habré there were several articles on this topic, very informative and well stated.
The techniques are excellent, but somehow they could not be applied in real life.

Under the cut - a small overview of the deplorable state of affairs in Perl and the separatist "it seems" solution.

So, why did not it go out to apply something in real code?
In fact, everything is quite clear - the available modules that declare the implementation of DI are difficult to understand and fantastically difficult to use, and the code turns out to be less and more. And very strange.
$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' ), } ) ); 

An example of the Bread :: Board manual, which (manual) is spread over 4 pages!

 $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, }, } } ); 

An example of IOC :: Slinky :: Container is already better, but still the same, if you think about it.
')
 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']); 

Example Peco :: Container - positioned as a “Light Inversion of Control (IoC) container”. Try to take the last line and follow what is happening in the reverse order. Still understand what's going on?

IMHO the problem is that these implementations are complex, overloaded with some features and as a result are non-smoking, inconvenient to use and can turn support into hell.

All that is needed from DIc is the ability to put a piece of code there and later get the result of its execution. Put the workpiece dbh - got a working handler at the output. No magic, create code from the configuration file and other academic pieces.

 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'); 

The Kaiten :: Container example is simple, clear and effective.

Examples and documentation included, you can take on the CPAN and github .

Questions, thanks, curses and rays of hatred can be published here or in any other way convenient to you.

Ps. If the module does not wish to be put, telling something like

 # 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 (>)... 

Join the thirsty patch Moo here .

Pps. And now in 3D! Supports dependency resolution.

Source: https://habr.com/ru/post/134891/


All Articles