Ok. Some of you might point out that Perl isn't the right choice if you're looking for some hefty performance in your applications, but I still want to solve this problem in Perl, and in the best possible way. Please excuse my English, as it's not my primary language.

First of all, let me tell you about my old way of doing things in my database-powered applications. Let's imagine we're having a Group class and a Person class. The Group class should have a method, get_members(), which should return a list of Person objects;

Person.pm
package Group; use strict; use warnings; use Person; sub new { my $proto = shift; my $class = ref( $proto ) || $proto; my $self = { 'group_id' => 0, 'name' => '', '_members' => [], }; bless( $self, $class ); return $self; } sub get_members { my $self = shift; my $members = $dbh->selectcol_arrayref('SELECT person_id FROM grou +p_member WHERE group_id = ' . $self->id()); foreach my $person_id ( @{$members} ) { push( @members, Person->new($person_id) ); } return \@members; } 1;
The code above is quite truncated, but I'll bet you get the idea of how things are working.

The problem, however, is that a call to Person->new() generates a new SQL query (which reads in information about the wanted person record), and generally some extra "class overhead". After some though, I came up with the following solution:

Person.pm
package Person; use strict; use warnings; use _Person; sub read { my $self = shift; my $id = shift || []; return [] unless ( $id ); my @objects = (); my $stRead = $dbh->prepare('SELECT person_id, firstname, lastname +FROM person WHERE person_id IN (' . join(', ', @{$id}) . ')'); $stRead->execute(); while ( my ($person_id, $firstname, $lastname) = $stRead->fetchrow +() ) { my $Person = _Person->new(person_id => $person_id, firstname => $firstname, lastname => $lastname); push( @objects, $Person ); } $stRead->finish(); return ( wantarray ) ? @objects : pop( @objects ); } 1;
_Person.pm
package _Person; use strict; use warnings; sub new { my $proto = shift; my $class = ref( $proto ) || $proto; my $self = { 'person_id' => 0, 'firstname' => '', 'lastname' => '', }; $self->_init( @_ ); return $self; } sub _init { my $self = shift; my %args = @_; return unless ( %args ); $self->person_id( $args{'person_id'} ); $self->firstname( $args{'firstname'} ); $self->lastname( $args{'lastname'} ); } sub person_id { my $self = shift; my $data = shift; $self->{'person_id'} = $data if ( defined $data ); return ( defined $self->{'person_id'} && $self->{'person_id'} =~ m +,^\d+$, ) ? $self->{'person_id'} : 0; } sub firstname { # Same as person_id(), except the obvious } sub lastname { # Same as person_id() and firstname(), except the obvious } 1;
Now, Group.pm's get_members() method would look something like this:
sub get_members { my $self = shift; my $members = $dbh->selectcol_arrayref('SELECT person_id FROM grou +p_member WHERE group_id = ' . $self->id()); return Person->read( $members ); }
This way, generating many Person objects requires only one call to the database.

Much of the code is very simplified, but I guess - and hope - you'll get the idea. I've become quite conservative in my OOP coding the last few years, and I have a feeling that the approach above is a bit hairy...?

Any comments, suggestions and general thoughts from those with more Perl wisdom than myself is highly appreciated!

Thanks in advance!

In reply to Battling with OOP performance by Evil Attraction

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.