Class::C3でFizzBuzzなんぞしてみる

微妙に違うバッチ処理スクリプトを大量に書いていたのですが、メンテナンスや再利用性を考えるとプラガブルな感じにしておくと良さそう。PerlモジュールにClass::C3ってのがあるので、これでうまい事できないかなと...

つーわけで、これを使って試しにFizzBuzzしてみました。

package Foo;
use base 'Class::C3::Componentised';
sub component_base_class { "Foo" }

sub new {
    my $class = shift;
    bless{n=>undef},$class;
}

sub call{
    my $self = shift;
    return;
}

package Foo::Buzz;
use base qw/ Foo /;

sub call{
    my $self = shift;
    my $n = [];
    for my $i (@{$self->{n}}){
       $i = 'Buzz' unless( $i =~ /(Fizz|Buzz)/ || $i%5 ); 
       push @{$n},$i;
    }
    $self->{n} = $n;
    $self->next::method();
    return;
}

package Foo::Fizz;
use base qw/ Foo /;

sub call{
    my $self = shift;
    my $n = [];
    for my $i (@{$self->{n}}){
       $i = 'Fizz' unless( $i =~ /FizzBuzz/ || $i%3 ); 
       push @{$n},$i;
    }
    $self->{n} = $n;
    $self->next::method();
    return;
}

package Foo::FizzBuzz;
use base qw/ Foo /;

sub call{
    my $self = shift;
    my $n = [];
    for my $i (@{$self->{n}}){
       $i = 'FizzBuzz' unless( $i%15 ); 
       push @{$n},$i;
    }
    $self->{n} = $n;
    $self->next::method();
    return;
}

package Foo::Hoge;
use base qw/ Foo /;

sub call{
    my $self = shift;
    $self->{n} = shift;
    $self->next::method();
    return $self->{n};
}

Foo::Hoge->load_components('FizzBuzz','Fizz','Buzz');
my $foo = new Foo::Hoge();
map{print "$_\n";} @{$foo->call([1..100])};

BaseクラスのClass::C3::Componentisedは、DBIx::Classにあったload_componentsを別モジュールとして分離実装したものです。モジュール名の配列を渡すと順番にに従って中のメソッドが実行されます。

Foo::Hoge->load_components('FizzBuzz','Fizz','Buzz');

今回の場合は以下の順番で処理され1から100までの数字が変換さるようになっています。

 ↓

  • Foo::Fizz->call() 3で割り切れたらFizz

 ↓

  • Foo::Buzz->call() 5で割り切れたらBuzz

Class::C3はデータにFilterをかけたいなどの横方向に拡張したい場合に使うと有効なようです。

あと、FizzBuzzの確認には

perl -MAcme::FizzBuzz -e ''

を使うと安心です(w
yappo++