Search code examples
perloopperl-criticbless

perl using bless self in script and PerlCritic


I am used to using $self for OO Perl even when I am just writing self-contained scripts without naming my package at all. For example, my script.pl would start like this:

use strict;
use warnings;
my $self = bless {};
$self->time_stamp(localtime(time()));
1;

sub time_stamp {
  my ($self,@args) = @_;
  # Getter/setter
  my $ftime_stamp;
  if( 1 < scalar @args ) {
    $ftime_stamp = strftime "%Y%m%d_%H%M%S", @args;
    $self->{'time_stamp'} = $ftime_stamp;
  }
  return $self->{'time_stamp'};
}
[...]

These scripts sometimes turn into proper modules, but some times I just let them be as such.

This though goes against Perl Critic of "One-argument blesses":

One-argument "bless" used at line 162, column 12.  See page 365 of PBP.  Severity: 5

Is there a clean way of naming my bless but still having everything contained in my script.pl?


Solution

  • Not everything criticized by perlcritic has to be fixed. But usually, it really is preferable to specify the package name for bless.

    If you don't declare a package name, your code implicitly is in package main. If you don't care about the actual name and want to refer to the current package, use the __PACKAGE__ symbol, e.g.:

    my $self = bless {} => __PACKAGE__;
    

    You could also write a little bit of boilerplate:

    sub new {
      my ($class) = @_;
      return bless {} => $class;
    }
    
    my $self = __PACKAGE__->new;
    

    Or you could use an object system like Moo:

    use Moo;
    has _time_stamp => (is => 'rw');
    
    sub time_stamp {
      my ($self, @args) = @_;
      if( 1 < scalar @args ) {
        $self->_time_stamp(strftime "%Y%m%d_%H%M%S", @args);
      }
      return $self->_time_stamp;
    }
    
    my $self = __PACKAGE__->new;  # a "new" is autogenerated