Accessing a container objects state from aggregated objects

D

Derek Basch

Hello all,

I am trying to do class aggregation properly in perl. I was wondering
what the best practices for accessing a container objects state from
the aggregated objects is.

For instance this is what I came up with:
-----------------------------------------------------------------------
use strict;
use warnings;

package Member_dev;
use Membership_dev;

sub new {
my $class = shift;
my $member_identifier = shift;
my $self = {
'address' => "yo momma's house"
};
bless ($self, $class);
$self->{'membership_dev'} = Membership_dev->new($self);
return $self;
}

package Membership_dev;
sub new {
my $class = shift;
my $self = {
'member' => shift
};
bless ($self, $class);
return $self;
}

sub suspend {
my $self = shift;
print "Address $self->{'member'}->{'address'} is suspended!";
}

package main;
my $member = Member_dev->new();
$member->{'membership_dev'}->suspend();
-----------------------------------------------------------------------

As you can see I am passing the member object reference to the
aggregated membership object. Then I can access the container objects
state information from the aggregated object. Is this a good idea? Is
there a better way to do this?

Thanks for the help,
Derek Basch
 
D

Derek Basch

This looks like a has-a situation with delegation of methods to member
objects. That is a standard technique. Whether there is a better one
in your situation isn't clear because you haven't described what the
situation is.

Anno

Yes, that is the situation that I was going for. Here is a description
of what I am using this technique for:

I have Members of a club and the Members have a Membership. So, Member
aggregates Membership.

The Member object holds some state information about the member such as
their address. I was wondering what the best way of accessing a Member
container objects address state from the aggregated object Membership
was.

Should I pass a reference to the Member object to the Membership object
in the Member constructor?

package Member;
sub new {
.........
bless ($self, $class);
$self->{'membership_dev'} = Membership_dev->new($self);
return $self;

}

Is that the best way?

Thanks,
Derek Basch
 
A

anno4000

Derek Basch said:
Yes, that is the situation that I was going for. Here is a description
of what I am using this technique for:

I have Members of a club and the Members have a Membership. So, Member
aggregates Membership.

The Member object holds some state information about the member such as
their address. I was wondering what the best way of accessing a Member
container objects address state from the aggregated object Membership
was.

Should I pass a reference to the Member object to the Membership object
in the Member constructor?

package Member;
sub new {
........
bless ($self, $class);
$self->{'membership_dev'} = Membership_dev->new($self);
return $self;

}

Is that the best way?

It is one way. If I'm not mistaken you're creating a cyclic reference
there, so you'd need a destructor in one of the classes to resolve that,
or use weak refs.

Alternatives are passing the Member object (or just the address) as
a parameter to the Membership method(s) that need(s) to know. Or
make the Membership method a Member method (to which, presumably,
the specific membership would have to be passed).

I'm sure there are other ways. Which one is "best" is ultimately
a design decision you must answer yourself.

Anno
 
D

Derek Basch

It is one way. If I'm not mistaken you're creating a cyclic reference
there, so you'd need a destructor in one of the classes to resolve that,
or use weak refs.

Ahhhh. Right you are. I never would have known that was a dangerous
thing to do. This article helped me figure it out as well:

http://www.perl.com/pub/a/2002/08/07/proxyobject.html?page=1
Alternatives are passing the Member object (or just the address) as
a parameter to the Membership method(s) that need(s) to know.

Like this?

package Membership;

sub suspend {
$self = shift;
$member = shift;
# do suspension stuff
}

package Member;

sub new {
my $class = shift;
my $self = {};
$self->{'membership'} = Membership->new($self);
bless ($self, $class);
return $self;
}

sub suspend {
$self->{'membership'}->suspend($self);
}

Doesn't this create another circular reference. I can see how the
references are more likely to go out of scope sooner. Wouldn't I need
to use the weakrefs here too?

Or make the Membership method a Member method (to which, presumably,
the specific membership would have to be passed).

I am guessing this is Similar to the example that Sinan gave earlier in
the thread?
I'm sure there are other ways. Which one is "best" is ultimately
a design decision you must answer yourself.

Anno

Yeah, I am starting to get a bit confused as to whether or not the
Member, Membership aggregation idiom is the best design for what I am
trying to do.

I have a large club with Members. Each Member has a Membership and I
regularaly perform actions on their membership such as suspend,
activate, extend, etc... It didn't make sense (to me) to have all the
Membership actions be part of their Member object so I created a
Membership object for each Member. The Member object is focused more on
storing the members state information (address, age, etc...).

My OO design/analysis skills are weak so any thoughts on how to better
handle this situation would be greatly appreciated.


Thanks A Million,
Derek Basch
 
A

anno4000

Derek Basch said:
Ahhhh. Right you are. I never would have known that was a dangerous
thing to do. This article helped me figure it out as well:

http://www.perl.com/pub/a/2002/08/07/proxyobject.html?page=1

In this case, ignoring reference cycles would lead to nothing worse
than a memory leak. Depending on the application that could be anything
from a minor disadvantage to a killer.
Like this?

package Membership;

sub suspend {
$self = shift;
$member = shift;
# do suspension stuff
}

package Member;

sub new {
my $class = shift;
my $self = {};
$self->{'membership'} = Membership->new($self);
bless ($self, $class);
return $self;
}

sub suspend {
$self->{'membership'}->suspend($self);
}

Yes, like that.
Doesn't this create another circular reference. I can see how the
references are more likely to go out of scope sooner. Wouldn't I need
to use the weakrefs here too?

No, there is no circularity until you *store* a reference in a structure
that (directly or indirectly) points back to the structure. Just using
such a reference is harmless.
Or make the Membership method a Member method (to which, presumably,
the specific membership would have to be passed).
[...]

Yeah, I am starting to get a bit confused as to whether or not the
Member, Membership aggregation idiom is the best design for what I am
trying to do.

I was wondering too...
I have a large club with Members. Each Member has a Membership and I
regularaly perform actions on their membership such as suspend,
activate, extend, etc... It didn't make sense (to me) to have all the
Membership actions be part of their Member object so I created a
Membership object for each Member. The Member object is focused more on
storing the members state information (address, age, etc...).

Aha. So each member has exactly one membership, not potentially multiple
memberships (in different clubs).
My OO design/analysis skills are weak so any thoughts on how to better
handle this situation would be greatly appreciated.

I would consider making Membership a base class of Member. That way
you can keep the definition of the Membership methods apart from the
Member methods, but you'll ultimately call them all on a Member object.
This only works when each Member has at most one Membership because
you can initialize Membership only once per Member object.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top