Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear wise Monks, I'm not sure if what I'm doing is bad practice or not (or just terrible code, please me gentle). I created a Log object singleton to use throughout a number of modules which interact. Is it ok to store the Log object inside other objects so that the Log objects logging methods can be utilized? Here's the code (stripped down). In package DoStuff I call the Log objects log routine.
package Log; my $singleton; sub new{ my ($class,$logpath) = @_; unless ( ref $singleton eq 'Log' ) { $singleton = {}; bless( $singleton, $class ); $singleton->create_path($logpath); } return $singleton; } sub create_path{ my ($self,$logpath) = @_; my $logfile = $logpath . 'yyyymmdd' . '.txt'; $self->{'log'} = $logfile; return; } sub get_log_instance { $singleton ||= (shift)->new(); } sub log { my $self = shift; my $error_msg = shift; my $logfile = $self->{'log'}; my $handle; open ( $handle, '>>', $logfile ) or die "Can't open $logfile: $!"; print {$handle} "ERROR: $error_msg\n"; close $handle; return; } 1; package DoStuff; use Log; sub new { my $class = shift; my $log_obj = Log->get_log_instance(); my $self = bless {}, $class; # Store log object. Is this OK to do? $self->{'log_obj'} = $log_obj; return $self; } sub get_log_obj { my $self = shift; return $self->{'_log_obj'}; } sub do_something { my $self = shift; ..... # Get log object and pass error msg to it's log sub routine $self->get_log_obj()->log('Error Error Error'); # Do some logging ..... return; } 1;

Replies are listed 'Best First'.
Re: Singleton Log Object
by blue_cowdawg (Monsignor) on Jan 08, 2013 at 20:08 UTC
        sub new{ my ($class,$logpath) = @_; unless ( ref $singleton eq 'Log' ) { $singleton = {}; bless( $singleton, $class ); $singleton->create_path($logpath); } return $singleton; }

    There's a couple of things I'd change:

    package Log; my $instance = undef; sub new { shift; unless ($instance){ $instance={}; bless $instance,"Log"; } return $instasnce; }
    You would not need the get_log_instance sub since
    | handwaving here my $log=new Log(); |
    would either return the instance in play already or create a new one it there wasn't one in play. Creating a singleton is something I do all the time. Especially for my logging module. :-)


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
      Great to get some feed back so promptly! You're the best, thanks so much.