The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Bread::Board::LazyLoader - lazy loader for Bread::Board containers

VERSION

version 0.02

SYNOPSIS

    package MyApp::IOC;
    use strict;
    use warnings;

    use Path::Class qw(dir);
    use Bread::Board::LazyLoader;

    # loads all *.ioc files under .../MyApp/IOC/
    # from each .../MyApp/IOC/<REL_PATH>.ioc file
    # a <REL_PATH> subcontainer is created
    # from .../MyApp/IOC/Root.ioc a root container is created
    #
    # examples
    # file .../MyApp/IOC/Root.ioc defines the root container
    # file .../MyApp/IOC/Database.ioc defines the Database subcontainer 
    # file .../MyApp/IOC/WebServices/Extranet.ioc defines the WebServices/Extranet subcontainer

    sub loader {  
        my $dir = __FILE__;
        $dir =~ s/\.pm$//;

        my $loader = Bread::Board::LazyLoader->new;

        dir($dir)->traverse(sub {
            my ($f, $cont, $rel) = @_;

            return $cont->( [ $rel ? @$rel : (), $f->basename ] ) if -d $f;
            my ($name) = -f $f && $f->basename =~ /(.*)\.bb$/
                or return;

            $loader->add_file( $f,
                $name eq 'Root' && @$rel == 1
                ? ()
                : join( '/', ( splice @$rel, 1, ), $name ) );
        });
        return $loader->build;
    }

    sub root {
        my $this = shift;
        return $this->loader(@_)->build;
    }

DESCRIPTION

Imagine we have a large Bread::Board root container (with nested subcontainers). This container is used among scripts, psgi application files, ... Each place of usage uses only part of the tree (usually it resolves one service only).

You can have the root container defined in a single file, but such extensive file can be hard to maintain. Also the complete structure is loaded in every place of usage, which can be quite consuming (if some part of your tree is an OX aplication for example).

Bread::Board::LazyLoader enables you to define your containers (subcontainers) in independent files which are loaded lazily when the container is asked for ($parent->get_subcontainer).

Having our IOC root defined like

    my $dir     = '...';
    my $builder = Bread::Board::LazyLoader->new;
    $builder->add_file("$dir/Root.ioc");
    $builder->add_file( "$dir/Database.ioc"    => 'Database' );
    $builder->add_file( "$dir/WebServices.ioc" => 'WebServices' );
    $builder->add_file( "$dir/Integration.ioc" => 'Integration' );
    $builder->build;

we can have Integration/manager service resolved in a script while the time consuming WebServices container (OX application) is not loaded.

Definition file

Definition file for a container is a perl file returning (the last expression of file is) an anonymous subroutine.

The subroutine is called with the name of the container and returns the container (Bread::Board::Container instance) with the same name.

The file may look like:

    use strict;
    use Bread::Board;

    sub {
        my $name = shift;
        container $name => as {
            ...
        }
    };

Of course we can create the instance of our own container

    use strict;
    use Bread::Board;
    
    use MyApp::Extranet; # our big OX based application

    sub {
        my $name = shift;
        MyApp::Extranet->new(
            name => $name
        );
    };

A single container can be built from more definition files, the subroutine from second file is then called with the container created by the first subroutine call: my $container = $sub3->($sub2->($sub1->($name)));

The construction container $name => as { ... }; from Bread::Board can be used even when $name is a container, not a name.

The definition files (the subroutines) are applied even if the container was already created inside parent container.

METHODS

new

Parameterless constructor

add_file(FILE, [ UNDER ])

Adds a file building the current or nested container. Optional second parameter is is a path to nested container.

add_code(CODEREF, [ UNDER ])

Similar to add_file, but the anonymous subroutine is passed directly not loaded from a file.

build

Builds the current container. Each call of <build> returns a new container.

AUTHOR

Roman Daniel <roman.daniel@davosro.cz>

COPYRIGHT AND LICENSE

This software is copyright (c) 2013 by Roman Daniel.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.