Why is Perl so rarely used IoC, DI and the magic pill Kaiten :: Container

    I think many people understand the importance of the Inversion of Control (Ioc) and Dependency Injection (DI) bazvords. If not very, but interestingly - there were several articles on this subject on the Habré, it was very informatively and readily presented.
    The techniques are excellent, but somehow they could not be applied in real life.

    Under the cutscene - a small overview of the deplorable state of affairs in Perl and an independent “seems” solution.

    So, why didn’t it come out to apply something in real code.
    In fact, everything is quite understandable - the available modules that declare the DI implementation are difficult to understand and fantastically difficult to use, and the code is 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 from 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,
                    },
                }
            }
        );
    

    Example IOC :: Slinky :: Container, already better, but still the same tin, 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 whole problem is that these implementations are complex, overloaded with some features and as a result are invisible, 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. We put the dbh blank - we got a working handler at the output. No magic, creating code from a configuration file and other academic stuff.

    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 efficient.

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

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

    PS. If the module does not want to be installed, reporting 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 craving Moo patch here .

    PPS And now in 3D! Dependency resolution supported.

    Also popular now: