bless($args, $class) is a bad practice

さいきん散見される以下のようなコードは悪いコードです。

# usage: Foo->new({ age => 42 })
sub new {
  my($class, $args) = @_;
  return bless $args, $class;
}

それは、ハッシュリファレンスと想定される$argsのそのままつかっているため、引数としてハッシュリテラル以外の何かを渡すと予期しない動作を引き起こすという点です。

たとえば、以下のような使い方は問題を引き起こします。

my %args = (age => 20);
my $o1 = Foo->new(\%args);
my $o2 = Foo->new(\%args);

# ここで $o1 と $o2 は同じオブジェクトになってしまう

このような場合、$argsはコピーすべきです*1。またついでにハッシュリファレンスではなくkey-value pairsを受け取れるようにしておくと無難です。

sub new {
  my $class = shift;
  my %args  = (@_ == 1 ? %{$_[0]} : @_);
  return bless \%args, $class;
}

ただし、newに関するベストプラクティスは、自分でnewを書かずにクラスビルダーを使うというものです。上記のコピーする版でも引数の仕様がまったくわかりません。MouseやClass::Accessor::Liteなどのクラスビルダーを使うと引数の仕様を(ある程度)コードで記述できるので特に理由がない限りはクラスビルダーを使うべきです。

*1:浅いコピーか深いコピーかは場合によるでしょう