Accessing a container objects state from aggregated objects

Discussion in 'Perl Misc' started by Derek Basch, Aug 15, 2006.

  1. Derek Basch

    Derek Basch Guest

    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
    Derek Basch, Aug 15, 2006
    #1
    1. Advertising

  2. Derek Basch

    Derek Basch Guest

    > 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
    Derek Basch, Aug 15, 2006
    #2
    1. Advertising

  3. Derek Basch

    -berlin.de Guest

    Derek Basch <> wrote in comp.lang.perl.misc:
    > > 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?


    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
    -berlin.de, Aug 15, 2006
    #3
  4. Derek Basch

    Derek Basch Guest

    > 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
    > 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
    Derek Basch, Aug 15, 2006
    #4
  5. Derek Basch

    -berlin.de Guest

    Derek Basch <> wrote in comp.lang.perl.misc:
    > > 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


    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.

    > > 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);
    > }


    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
    -berlin.de, Aug 16, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Vivi Orunitia
    Replies:
    11
    Views:
    4,443
    Martijn Lievaart
    Feb 4, 2004
  2. Maitre Bart
    Replies:
    2
    Views:
    506
    Maitre Bart
    Feb 11, 2004
  3. Steven T. Hatton
    Replies:
    4
    Views:
    3,861
    Rob Williscroft
    Dec 5, 2004
  4. Replies:
    4
    Views:
    776
    Daniel T.
    Feb 16, 2006
  5. Ruby Freak

    aggregated blogs on ruby:New site

    Ruby Freak, Sep 12, 2006, in forum: Ruby
    Replies:
    9
    Views:
    92
    Rick DeNatale
    Sep 13, 2006
Loading...

Share This Page