It’s been quite a while since I last posted here. Since my last entry I got a new job, got married, went on honeymoon (got back yesterday!) and spent quite a lot of time maintaining legacy Perl code.

One thing I see a lot is sharing objects by passing them to the constructor of a new object. This is fine until you’re dealing with complicated sets of objects within objects.

#!/usr/bin/perl

use strict;

# Read some variables out of a configuration file.
my $config = get_config($config_file);

# Create a new object which contains an object which uses some values from the config.
my $object = MyObject->new($config);
$object->do_something();

package MyObject;

sub new {
    my $class = shift;
    my $config = shift;

    # Store the config incase we create any objects which need it.
    my $self = { 'config' => $config };

    return bless $self, $class;
}

sub do_something {
    my $self = shift;

    my $object2 = MyObject2->new($self->{'config'});

    return $object2->do_something_else();
}

MyObject is now holding a reference to the config object which it doesn’t need directly. This will only get worse if MyObject2 needs another object which requires the config object, etc.

Instead we could use a singleton object:

package MyConfigObject;

use strict;
use Carp;

my $config = undef;

sub new {

    if(!$config) {
        my $class = shift;
        my $config_file = shift;

        croak unless $config_file;

        $config = bless {}, $class;
        $config->parse_file($config_file);
    }

    return $config;
}

The example above changes to:

#!/usr/bin/perl

use strict;

# Create a new object to hold the values from our config file.
my $config = MyConfigObject->new($config_file);

# Create a new object which contains an object which uses some values from the config.
my $object = MyObject->new();
$object->do_something();

package MyObject;

sub new {
    my $class = shift;

    return bless {}, $class;
}

sub do_something {
    my $self = shift;

    my $object2 = MyObject2->new();

    return $object2->do_something_else();
}

package MyObject2;

sub new {
    # Get the config object
    my $config = MyConfigObject->new();

    # Do some stuff with it!
}

Whenever we need to use a value from the config file, we create a new MyConfigObject and get the instance we already created without having to reparse the config file or maintain complicated links through parent objects.