On Thu, Feb 23, 2012 at 12:57:26PM +0700, Bill Moseley wrote:
> I often have classes that abstract out the work of fetching data from
> multiple sources -- so I have attributes that hold instances of the objects
> that do the actual work. Each of these objects need their own config.
>
> I've used three approaches to pass config to the contained objects, but
> each seems a bit cumbersome. Just wondering if there's other ideas.
>
>
> One is to have a HashRef attribute in the "parent" that just gets passed to
> the "child" object's constructor. This doesn't work so good if the class
> is turned into a command line tool.
>
> I've also use a configuration class and pass an instance of that from the
> parent to the child. Essentially the same as the hashref approach.
Whoa whoa whoa, stop right there. Have you seen MooseX::SimpleConfig and
MooseX::Getopt? This is a very common design pattern in Moose:
package MyChild;
use Moose;
with 'MooseX::Getopt', 'MooseX::SimpleConfig';
has configfile => (
is => 'ro', isa => 'Str',
documentation => 'the configfile for MyChild',
default => sub {
my $class = shift;
$class = blessed($class) || $class;
return '/some/path/myclass_config.yml';
},
);
has $_ => (
is => 'ro', isa => 'Str',
) foreach @my_config_var_names;
package Container;
use Moose;
has child => (
is => 'ro', isa => 'MyChild',
lazy => 1,
default => sub {
my $self = shift;
MyChild->new_with_config(%otheroptions);
},
handles => {
%delegations_here,
},
);
# usecase 1: MyChild springs into existence on its first use, already
# pre-configured with values from myclass_config.yml.
$container->child->somesub;
# usecase 2: use MyChild on its own, from a wrapper script. @ARGV is
# automatically parsed via MooseX::Getopt and used as constructor args for
# MyChild. The config file is also parsed and used for any configs that
# aren't overridden from the command line.
#/usr/bin/env perl
use MyChild;
my $child = MyChild->new_with_options;
./myscript --opt1 val1 --opt2 val2