2020年はどうなるかは置いておいて、2019年の最先端のPerl開発ボイラープレート - Qiitaを参考にする。
- Moo
- strictures
- Function::Parameters
- Type::Tiny
あたりを使う。
最近、Mooseを使ってデザインパターンを実装してみてるのでこれらを使って、Chain of Responsibilityパターンをなんとなく書いてみた。ちなみに以下のJava実装が解説を含めて分かりやすいので、ポーティングするような形で書いている。
Java実装との最大の差はInterfaceとか抽象クラスという概念がp5-Moose/Mooにはないことなんだけど、Roleがハマる時はRoleを使って表現している(といってもそのまま書き写すんじゃなくてPerlっぽい書き方で書いてるつもり)。
Support.pm
。Javaでは抽象クラスで書かれてたけど、今回はRoleを使った。
package Support; use Moo::Role; use strictures 2; use namespace::clean; use Function::Parameters; use Types::Standard qw/Str Object/; has 'name' => ( is => 'ro', isa => Str, ); has 'next' => ( is => 'rw', isa => Object, ); requires 'resolve'; method support($trouble) { if ( $self->resolve($trouble) ) { $self->done($trouble); } elsif ( $self->next ) { $self->next->support($trouble); } else { $self->fail($trouble); } } method done($trouble) { print $trouble->to_string . " is resolve by [" . $self->name . "].\n"; } method fail($trouble) { print $trouble->to_string . " is cannot be resolved.\n"; } 1;
method
カッコイイ。ほんとはnext
プロパティでSupportロールを実装しているクラスのインスタンス、ってのを指定したかったけど(Mooseだとできる)、Type::Standard
にはそういうのなさそうなので(RoleName
っていうTypeならある)Object
を指定してる。
SpecialSupport.pm
では上記のRoleをwith
して実装。
package SpecialSupport; use Moo; use strictures 2; use namespace::clean; use Function::Parameters; use Types::Standard qw/Int/; with 'Support'; has 'number' => ( is => 'ro', isa => Int, ); method resolve($trouble) { return $trouble->number == $self->number; } 1;
method
カッコイイ(2度目)。
Data::Validatorでやってたような、メソッドの引数の型チェックをType::Tinyと組み合わせて「かっこよく」書けるかな?って思った。以下、実装の全部。