Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
(Sorry for the oddball title... I don't know what else to call it.)
I have got my topmost module that uses several other modules under it's own namespace (so we've got My::Main, My::Main::Child1, My::Main::Child2, etc.). Each of these sub-modules (as well as the topmost module) needs access to a LWP::UserAgent object. What is the best way to accomplish this task of sharing the object? Here is a simple setup of what I am talking about:
=for discussion The Problem: The problem is labelled in My::Main::Child1->usechild(). We wish to access the LWP::UserAgent object, located in the blessed hashref of My::Main::Child1's parent (My::Main is the parent in this case). =cut # My/Main.pm package My::Main; use strict; use LWP::UserAgent; use My::Main::Child1; sub new { my ($class) = @_; my $self = bless( {}, $class ); $self->{_ua} = LWP::UserAgent->new(); return( $self ); } sub newchild { my ($self) = @_; return( My::Main::Child1->new() ); } # My/Main/Child1.pm package My::Main::Child1; use strict; sub new { my ($class) = @_; return( bless( {}, $class ) ); } sub usechild { my ($self) = @_; # PROBLEM LINE! my $res = $self->(...)->{_ua}->get( 'http://www.example.com' ); return( $res->code(), $res->content() ); } # usemain.pl #!/usr/bin/perl -w use strict; use My::Main; my $main = My::Main->new(); my $child = $main->newchild(); my ($code, $content) = $child->usechild();
Below are three (horrible?) solutions I came up with, the first two of which seems okay to me, but I am not sure. The third one works of course, but it causes a lot of headaches if you need the same object instance to be used by all modules -- not to mention the system overhead of creating multiple objects when a single object would do. I think I am leaning heavily towards solution #2, but I do not know if there are any dangers involved.
=for explanation Solution 1: We pass the same LWP::UserAgent object into each child. This way, we don't have extra needless objects created in each child. The mechanics seem only slightly ugly, as we are throwing references all over the place. The major benefit I see is that this will keep object data persistent across all modules (for example, if we pass "agent => 'my special useragent'" to LWP::UserAgent->new() in the topmost module, all child modules will have the same useragent. =cut # My/Main.pm package My::Main; use strict; use LWP::UserAgent; use My::Main::Child1; sub new { my ($class) = @_; my $self = bless( {}, $class ); $self->{_ua} = LWP::UserAgent->new(); return( $self ); } sub newchild { my ($self) = @_; return( My::Main::Child1->new( $self->{_ua} ) ); } # My/Main/Child1.pm package My::Main::Child1; use strict; sub new { my ($class, $ua) = @_; my $self = bless( {}, $class ); $self->{_ua} = $ua; return( $self ); } sub usechild { my ($self) = @_; my $res = $self->{_ua}->get('http://www.example.com'); return( $res->code(), $res->content() ); } =for explanation Solution 2: Similar to solution #1, but instead of passing each object we want to share with the child modules, we pass into each child's constructor our entire self. This way we just shove the entire parent object into a {_parent} key in the child's blessed hashref and then we can access all the parent's data. This appeals to me quite a bit, but it seems careless. Are there any dangers or reasons as to why we would not want to do this? =cut # My/Main.pm package My::Main; use strict; use LWP::UserAgent; use My::Main::Child1; sub new { my ($class) = @_; my $self = bless( {}, $class ); $self->{_ua} = LWP::UserAgent->new(); return( $self ); } sub newchild { my ($self) = @_; return( My::Main::Child1->new( $self ) ); } # My/Main/Child1.pm package My::Main::Child1; use strict; sub new { my ($class, $parent) = @_; my $self = bless( {}, $class ); $self->{_parent} = $parent; return( $self ); } sub usechild { my ($self) = @_; my $res = $self->{_parent}->{_ua}->get( 'http://www.example.com' ); return( $res->code(), $res->content() ); } =for explanation Solution 3: The topmost module and each child create and use their own (independant) object instance. Not only does this create additional needless objects, but since each object instance is completely separate from the others, such a system will fail if we want to use this sort of thing in a situation where data persistence must be kept valid in one object acrosss multiple modules. For example, if we pass "agent => 'my special useragent'" to LWP::UserAgent->new() in the topmost module, all child modules will NOT have the same useragent. We would have to update the topmost module to pass the useragent to each child object, and update each child to pass the useragent to it's own LWP::UserAgent constructor. =cut # My/Main.pm package My::Main; use strict; use LWP::UserAgent; use My::Main::Child1; sub new { my ($class) = @_; my $self = bless( {}, $class ); $self->{_ua} = LWP::UserAgent->new(); return( $self ); } sub newchild { my ($self) = @_; return( My::Main::Child1->new() ); } # My/Main/Child1.pm package My::Main::Child1; use strict; use LWP::UserAgent; sub new { my ($class) = @_; my $self = bless( {}, $class ); $self->{_ua} = LWP::UserAgent->new(); return( $self ); } sub usechild { my ($self) = @_; my $res = $self->{_ua}->get('http://www.example.com'); return( $res->code(), $res->content() ); }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Sharing objects between modules
by Corion (Patriarch) on May 05, 2004 at 06:25 UTC | |
|
Re: Sharing objects between modules
by Fletch (Bishop) on May 05, 2004 at 01:38 UTC | |
|
Re: Sharing objects between modules
by dragonchild (Archbishop) on May 05, 2004 at 02:18 UTC | |
|
Re: Sharing objects between modules
by pizza_milkshake (Monk) on May 05, 2004 at 02:02 UTC | |
by chromatic (Archbishop) on May 05, 2004 at 04:54 UTC |