ハッシュベースのオブジェクト指向を見直そう




  1. Perl




  2. 読み物


 僕自身はハッシュベースのオブジェクト指向が好きです。mopは簡単なことをするには複雑すぎると感じます。mopをコアに導入するか、いつできるかで、何年も何年もかかるなら、先にハッシュベースのオブジェクト指向モジュールをひとつコアに入れてほしい。これができたら、Perlユーザーの利便性はものすごく上がると思う。

 僕自身はmopにはあんまり期待していない。なぜならハッシュベースのオブジェクト指向で十分すぎるクラスが作れるからだ。ハッシュベースのオブジェクト指向は、簡潔なのに、機能としては必要十分なクラスを作成することができる。

 ハッシュベースのオブジェクト指向の利点を書いていく。

コンストラクタのパフォーマンス

 ハッシュベースのオブジェクト指向のほうがコンストラクタの生成のパフォーマンスはだいぶといい。

my $obj = SomeClass->new;

 これは、受け取った値を単純にハッシュに格納してblessしているからだ。パフォーマンスなんてと思うかもしれないけれど、実は大きなフレームワークにもなってくると、コンストラクタ生成処理がものすごく多い回数を使っていて、ここの部分で遅くなっているということもある。

 そんなことで悩むんだったら、最初からハッシュベースのオブジェクト思考で書いて、パフォーマンスが速いほうがよいと思う。

アクセッサのパフォーマンス

 アクセッサというのは、頻繁に呼ばれる。もしアクセッサを大量に呼ぶ部分で、モジュールのパフォーマンスネックが発生していたらどうすればいいだろう。こんなときも、ハッシュベースのオブジェクト指向なら簡単に解決する。

 それは、アクセッサの呼び出しをハッシュへのアクセスに変更すればよいだけだからだ。これで20〜30倍くらいは速くなる。

# メソッド呼び出し
$self->title;

# ハッシュアクセス
$self->{title}

 もしmopで書いていたとしたら、こんなことはできないはず。

シンプル イズ ベスト

 たくさんの機能はなくても、シンプルなオブジェクト指向モジュールで、きれいに実装された大きなフレームワークを実装することができる。これはMojoliciousなんかのフレームワークをみてみると、簡潔なオブジェクト指向モジュールで、よく整理されたクラスがきちんとできることがわかる。

package SomeClass;
use Mojo::Base -base;

has x => 0;
has y => 0;

 アクセッサの生成と、デフォルト値が設定できれば、十分なことがほとんどだ。複雑だと、何かと負担は多くなる。

クラス設計には単一継承と委譲を使うのがわかりやすい

 クラスを設計するときは、単一継承と委譲というテクニックを使うのがよいと感じます。この方針でクラスを設計するとクラスはわかりやすくなります。多重継承を使う必然性はなくて、クラスの構成を複雑にしがちになると思います。

 たとえば単一継承で間に合わなくなった場合は委譲を使います。Rを継承して、クラスQの機能をクラスPに追加したい場合を考えましょう。このような場合は、オブジェクトQを生成して、オブジェクトPに持たせます。これが委譲というテクニックです。

package P;
use Mojo::Base 'R';

use Q;

has q => sub { Q->new };

 このようにすればクラスQの機能を利用できるクラスPができますね。もちろんRを単一継承していますから、Rの機能は直接Pから利用できます。

オーバーライドが直感的

 たとえばサブクラスでコンストラクタをオーバーライドしたいとしますね。ハッシュベースのオブジェクト指向であれば、その操作は直感的で、他の言語でもなじみがある書き方になります。

sub new {
  my $self = shift->SUERP::new(@_);

  # ゴニョゴニョ

  return $self;
}

 mopのBUILDとかBUILDARGSというのは、わかりにくいです。

デストラクタはDESTROY

 デストラクタはPerlの習慣どおりDESTROYです。わざわざmopのDEMOLISHを覚える必要もないです。

ハッシュベースのオブジェクト指向モジュールをお勧めします

 メタオブジェクトプロトコルベースのオブジェクト指向よりも、ハッシュベースのオブジェクト指向を僕はお勧めします。コアにも、ハッシュベースのオブジェクト指向モジュールがひとつ入ってほしいです。

 メタオブジェクトプロトコルベースのオブジェクト指向は、一時あおられまくって、すごいものだと思われていたけれど、僕はそれには賛同しません。