I wanted to build an awesome place for people to discuss module specific issues, but I don't have any more time for this, and there are much better places to discuss Perl-related issues. I'd recommend asking your question on Stack Overflow or on Perl Monks.
If you are looking for a Perl tutorial or Perl-related news, I hope these links will serve you well.
Posted on 2012-05-17 09:45:42.220573-07 by wayan
Bread::Board service to be reevaluated in constructed objects

Constructing my objects via IoC framework (Bread::Board) I found quite typical pattern in my code.

Simple example: I have a Synchronizer object (for copying some files). Synchronizer uses Transport object (SFTP client maybe) to transfer physical files.

If Transport instance is same for whole lifetime of Synchronizer, it can be made into an attribute and objects can be constructed via simple constructor injection:

{ package Synchronizer; use Moose; has transport => (is => 'ro', required => 1); } { package Transport; use Moose; } use Bread::Board; my $root = container Root => as { service transport => ( class => 'Transport' ); service synchronizer => ( class => 'Synchronizer', dependencies => wire_names('transport'), lifecycle => 'Singleton', ); }; my $synchronizer = $root->resolve( service => 'synchronizer' ); warn $synchronizer->transport; warn $synchronizer->transport;

But what if I want that every call of $synchronizer->transport returns new instance of Transport, i.e. whenever $synchronizer->transport is called transport service is reevaluated (->get is called)?

The only way I found how to was to create new (concrete) BBSynchronizer class and wire the Bread::Board service into its instances. Something like:

{ package Transport; use Moose; } { package Synchronizer; use Moose; sub transport {...} # unimplemented } { package BBSychronizer; use Moose; extends 'Synchronizer'; has __transport_service => ( is => 'ro', handles => {transport => 'get'} ); } use Bread::Board; my $root = container Root => as { service transport => ( block => sub { return Transport->new; }, ); service synchronizer => ( class => 'BBSychronizer', block => sub { my $s = shift; return $s->class->new(__transport_service => $s->fetch('transport')); }, ); }; my $root2 = container Root => as { service transport => ( block => sub { return Transport->new; }, ); service __transport_service => ( block => sub { shift()->fetch('transport'); } ); service synchronizer => ( class => 'BBSychronizer', dependencies => wire_names('__transport_service'), ); }; my $synchronizer = $root->resolve( service => 'synchronizer' ); my $synchronizer2 = $root->resolve( service => 'synchronizer' ); warn $synchronizer2->transport; warn $synchronizer2->transport;

I slightly prefer second solution, where synchronizer is created via simple constructor injection. The __transport_service seems like lazy alias where get on alias returns the aliased service not its value.

Maybe the whole topic is more IoC than Bread::Board related and the solution obvious but I appreciate any comments.

Roman Daniel
Direct Responses: Write a response