Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Keeping relationally child objects alive with Moo

by anonymized user 468275 (Curate)
on Sep 21, 2017 at 10:24 UTC ( [id://1199820]=perlquestion: print w/replies, xml ) Need Help??

anonymized user 468275 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, The concept of inheritance carries with it a concept of parent and child, but what if I want a relational parent/child model?

So using Moo, I tried this:

package Myproject::Model; use Moo; has table => (is => 'rw'); sub newtable { my ($self, $table) = @_; my $tob = Myproject::Model::Table->new( # also uses Moo and define +s these ro attributes:- name => $table, model => $self, ); $self->table or $self->table({}); my $tables = $self->table; $tables -> {$table} = $tob; } 1;
Problem is that sometimes a $tob gets destroyed in spite of being nested in a living model object.

But rather than hack my way around what I did, I am wondering if I am missing a tried and tested way of storing relationally child objects in their relationally parent object (including if necessary upgrading from Moo to Moose). Many thanks in advance for suggestions (I am looking for architectural insight/tips rather than merely fixing the code I already have).

One world, one people

Replies are listed 'Best First'.
Re: Keeping relationally child objects alive with Moo
by choroba (Cardinal) on Sep 21, 2017 at 12:50 UTC
    What you describe is called "composition", and it's often accompanied by "delegation" where the outer object delegates some of its method to the inner one. It's a common pattern and it should work flawlessly in Moo.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      That's reassuring, but what about the way I am doing it:
      $self->attribute->{'key'} = $childObject;
      Is this the right way to assign one of many relationally child objects to the relational parent object? Having had some problems I worked around explicitly, I am worried that the reference to the inner object in the above construction is too remote to persist indefinitely just because the parent object persists indefinitely.

      One world, one people

        So, what does ->attribute return?

        If it returns a hashref that is kept alive by $self, you should be fine.

        If it returns something else, you might have a problem.

        But we cannot tell without seeing some representative example.

Re: Keeping relationally child objects alive with Moo
by choroba (Cardinal) on Sep 21, 2017 at 16:19 UTC
    Oh wait, you store $self in the model attribute of the table! It creates a reference cycle, so weird things can happen. You can try storing a weakened reference there instead.

    For example, you can undef the model, but its destructor isn't called, as it's still referenced from the tables:

    #!/usr/bin/perl use warnings; use strict; { package Myproject::Model::Table; use Moo; has name => (is => 'ro'); has model => (is => 'ro'); } { package Myproject::Model; use Moo; has table => (is => 'rw'); sub newtable { my ($self, $name) = @_; my $tob = 'Myproject::Model::Table'->new( name => $name, model => $self, ); $self->table or $self->table({}); $self->table->{$name} = $tob; } sub DESTROY { print "Good bye\n"; } } my $model = 'Myproject::Model'->new; $model->newtable('t1'); undef $model; # No destructor called here. use Data::Dumper; print Dumper $model;

    To get the destructor called, you can modify the definition of the model attribute like this:

    has model => (is => 'ro', weak_ref => 1);

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      I think you are clearly on the right track, but it's a pity I would want to strengthen rather than weaken these references. So it seems I am still looking for a fundamental change in how I am trying to store multiple objects of one class in a single object of another, because my code will be unmaintainable as it stands and needs to go in a simpler direction from where it has been going in my efforts to fix this. Next experiments are I am going to look into applying formal inheritance to Table, possibly with a root ancestor class for Model and Table and as a last resort removing the Table class and moving all its methods and attributes to Model and using just hash references to each table rather than objects. I can certainly get rid of all my workaround code if I do that.

      One world, one people

Re: Keeping relationally child objects alive with Moo
by Anonymous Monk on Sep 21, 2017 at 10:44 UTC
    Problem is that sometimes a $tob gets destroyed in spite of being nested in a living model object.

    that should not happen unless you are using weak references, please show an SSCCE to reproduce

      Nope, as I said, I want to get the basic approach right as the priority, only if the issue were unavoidable from the outset for lack of a better approach would it be sound to pursue it by keeping the basics and looking at the code in detail.

      One world, one people

        you claimed that objects were getting destroyed even though you still have a reference to them, that should not happen, and if it is, then you've either found a serious bug in Perl or a serious bug in your code. so that needs to be tracked down and fixed before discussing the "basic approach", since obviously there is something wrong with it right now. SSCCE

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1199820]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (6)
As of 2024-04-23 12:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found