リスト6.51〜6.54まで
一気にまとめたコードがこれ。
途中でしれっと出てくる Money クラスの add メソッドも書いております。
・・・Perl で書き換えながらめっちゃ書きにくさを感じることがあります。
このコードだと、interface の HotelRates の中で分岐コードを書くところ。
まぁ、ここで書いているのは「悪い(例示の)コード」なので、書きにくくて正解なんですけどね。
そうそう。
途中、コメントアウトしたところがあります。
# return $self->fee()->add( Money->new( amount => 3000 ) ); my $money = $self->fee(); return $money->add( Money->new( amount => 3000 ) );
1行でメソッドチェーンでかけるんですが、途中途中で返り値はなんだっけ・・・?
値?値オブジェクト?
みたいになったので、統一した方がいいんだろうなぁ、と思いました。
ここクリックして展開
use strict; use warnings; use Function::Parameters; use feature qw/say/; package Money { use Carp qw/croak/; use Mouse; use namespace::autoclean; use Readonly; use constant { MIN => 0 }; has amount => ( is => 'ro', isa => 'Int', required => 1, ); method add($other) { my $added = $self->amount() + $other->amount(); return Money->new( amount => $added ); } __PACKAGE__->meta->make_immutable(); } # 宿泊料金を表すロール package HotelRate { use Mouse::Role; requires 'fee'; fun busy_season_fee($self) { if ( ref $self eq 'RegularRates' ) { # return $self->fee()->add( Money->new( amount => 3000 ) ); my $money = $self->fee(); return $money->add( Money->new( amount => 3000 ) ); } elsif ( ref $self eq 'PremiumRates' ) { # return $self->fee()->add( Money->new( amount => 5000 ) ); my $money = $self->fee(); return $money->add( Money->new( amount => 5000 ) ); } } } #通常宿泊料金 package RegularRates { use Mouse; use namespace::autoclean; with 'HotelRate'; method fee() { return Money->new( amount => 7000 ); } __PACKAGE__->meta->make_immutable(); } # プレミアム宿泊料金 package PremiumRates { use Mouse; use namespace::autoclean; with 'HotelRate'; method fee() { return Money->new( amount => 12000 ); } __PACKAGE__->meta->make_immutable(); } package main; # 追加した繁忙期ロジック # 通常宿泊料金&繁忙期 my $regular_rate = RegularRates->new(); say $regular_rate->fee->amount(); # 7000 say $regular_rate->busy_season_fee()->amount(); # 10000 # プレミアム宿泊料金&繁忙期 my $premium_rate = PremiumRates->new(); say $premium_rate->fee->amount(); # 12000 say $premium_rate->busy_season_fee()->amount(); # 17000
リスト6.55 繁忙期料金を切り替えられるよう interface に定義
先の「悪いコード」に比べて、「いいコード」の方が直感的ですね。
あと、「図6.8」みたいなオブジェクト図のがいまいちわからなかったんですが、コードを見てからだと理解できるという。
というか、オブジェクト指向も書物を読んだだけではわからなくて、書いてみて、書き続けてやっとわかるみたいな。
割と脳筋使うところだなぁという感じです。
ここクリックして展開
use strict; use warnings; use Function::Parameters; use feature qw/say/; package Money { use Carp qw/croak/; use Mouse; use namespace::autoclean; has amount => ( is => 'ro', isa => 'Int', required => 1, ); method add($other) { my $added = $self->amount() + $other->amount(); return Money->new( amount => $added ); } __PACKAGE__->meta->make_immutable(); } # 宿泊料金を表すロール package HotelRate { use Mouse::Role; requires qw/fee busy_season_fee/; } #通常宿泊料金 package RegularRates { use Mouse; use namespace::autoclean; with 'HotelRate'; method fee() { return Money->new( amount => 7000 ); } method busy_season_fee() { my $money = $self->fee(); return $money->add( Money->new( amount => 3000 ) ); } __PACKAGE__->meta->make_immutable(); } # プレミアム宿泊料金 package PremiumRates { use Mouse; use namespace::autoclean; with 'HotelRate'; method fee() { return Money->new( amount => 12000 ); } method busy_season_fee() { my $money = $self->fee(); return $money->add( Money->new( amount => 5000 ) ); } __PACKAGE__->meta->make_immutable(); } package main; # 追加した繁忙期ロジック # 通常宿泊料金&繁忙期 my $regular_rate = RegularRates->new(); say $regular_rate->fee->amount(); # 7000 say $regular_rate->busy_season_fee()->amount(); # 10000 # プレミアム宿泊料金&繁忙期 my $premium_rate = PremiumRates->new(); say $premium_rate->fee->amount(); # 12000 say $premium_rate->busy_season_fee()->amount(); # 17000
よし、6章も残りは「フラグ引数」のみ。がんばろー
おまけ
MouseX::AttributeHelpers;
を使ってみたパターン。
さっぱり!
ここクリックして展開
use strict; use warnings; use Function::Parameters; use feature qw/say/; package Money { use Carp qw/croak/; use Mouse; use MouseX::AttributeHelpers; use namespace::autoclean; has amount => ( metaclass => 'Number', is => 'rw', isa => 'Int', required => 1, default => 0, provides => { add => 'add', } ); __PACKAGE__->meta->make_immutable(); } # 宿泊料金を表すロール package HotelRate { use Mouse::Role; requires qw/fee busy_season_fee/; } #通常宿泊料金 package RegularRates { use Mouse; use namespace::autoclean; with 'HotelRate'; method fee() { return Money->new( amount => 7000 ); } method busy_season_fee() { my $money = $self->fee(); return $money->add(3000); } __PACKAGE__->meta->make_immutable(); } # プレミアム宿泊料金 package PremiumRates { use Mouse; use namespace::autoclean; with 'HotelRate'; method fee() { return Money->new( amount => 12000 ); } method busy_season_fee() { my $money = $self->fee(); return $money->add(5000); } __PACKAGE__->meta->make_immutable(); } package main; # 追加した繁忙期ロジック # 通常宿泊料金&繁忙期 my $regular_rate = RegularRates->new(); say $regular_rate->fee->amount(); # 7000 say $regular_rate->busy_season_fee(); # 10000 # プレミアム宿泊料金&繁忙期 my $premium_rate = PremiumRates->new(); say $premium_rate->fee->amount(); # 12000 say $premium_rate->busy_season_fee(); # 17000