2008-05-25
Mooooooooooooooved
http://dann.g.hatena.ne.jp/dann/
Catalystで書く事がほとんどなくなったので、新しくグループを作成しました。Perl含めた雑多なネタは、上記のグループに書いていくことにします。
2008-05-20
コードは世界の共通言語
コードを書いて示せば、いいねといってくれる世界があるからオープンソースの世界は面白い。コードが共通の言語になっている。英語がつたなくたって、課題とコードを書けば、それを評価してもらえる世界がある。
コードを介して言語を超えて色んな人と繋がれることができる。色んなレベルの楽しみがあると思うのだけれど、純粋に技術を介して、人と物を作るところに楽しさがあると思っている。
Perl Newbieなサイト
おぉ、cooooooooooooooool!id:yappo++
newbie視点で色々と応援したいです!
ここ半年で色々と活動してみて、newbieでも飛び込んで何でもコードを書いてフィードバックをしてみたほうがいいなぁって思ってます。
脱newbieを目指して、KYせずに、色々とパッチを送ったり、いきなりhttp-engineのmoose化に関わってみたりとしてみてるわけですが、コミュニティにどんどん参加して、フィードバックをもらったほうが勉強になるし、何より楽しいです。
コードが汚かろうが美しかろうが、まずはアイデアとコードを書いてみて、コミュニティへのフィードバックしたほうが得られる物が大きい!コードかけなくたって疑問点があるだけだって、それだってフィードバックになりうると思って活動してます。
もっとPerlな人がnewbieであるなしかかわらず活動できる場があるといいなぁって思っていました。lazy-peopleはそんな場だったわけですが、こうやってperl-usersのような活動がもっと増えると、もっと色んな人が参加しやすくなって、色んな人がコミュニティを盛り上げていけるかもしれないですね。
Great!
# はてなに、perlerなgroupがあれば、すごいいいなぁと思ったり。
# はてなのグループじゃDISられるのかぁ。特定企業に結びついちゃうからなんですかねー
2008-05-19
Mooseのcommit bit
http://catalyst.g.hatena.ne.jp/dann/20080518/p2
で書いた内容をパッチにしてStevanに送ったら取り込んでくれることになった。ついでにcommit bitもstevanがくれた。本当のところ、commit bitは必要ないんだけどなぁ...
mstからcommit bitを貰ってくれと言われて少し困ったのだけれど、これも英語の勉強にいいかな。
# commit bitもらっちゃったので、before/after/aroundに対応したパッチにしてコミットすることに。moooooooooooose.
# commitしました. mstにaugmentとoverride用のTODO testを頂戴と言われたので、それもコミット。これで次のversionでは、method modifierに正規表現が使えるんじゃないかと。
Catalystの次期版はMooseベース@YAPC::Asia 2008
Catalystの話が全然ないじゃないか!とツッコミが入る今日この頃なので、Catalystについて書いておきます。
YAPC::Asia2008でCatalystの次期版はMooseベースだよ!とjrockwayのセッションでいっていたことでしょうか。言及はされませんでしたが、PluginはおそらくMooseのRoleをベースにしたDevel::REPL形式のプラグイン方式になるんじゃないかと思います。
Mooooooooooooooooooose!
# 既存のプラグインがどうなるのかは気になるところですね。雰囲気的には後方互換性が切れてしまう気もするんですが、どうなるんでしょうね。
2008-05-18
MooseのRoleでAOP
moose |
![]()
aroundのキーワードで指定できるメソッドが1つになってしまうからAOP目的では使えないけれど、around 'do_*' のように指定できるようになれば、Roleを複数のクラスに組み込めて使えるようになる。
だから、Transactionのように明示的にメソッドを指定したい場合には、aroundのmodifierにメソッドを登録するところを少し書き換えるだけでいけると思う。Mooseにパッチあてたいなぁ、これは。
package指定のようなjoinpointの指定はできないけれど、実際にパッケージ指定みたいなので使う場面はログ系くらしかないので、無くても困らないかもしれない。
で、実際、DIコンテナでweavingするよりも、こっちのほうが現実的かなぁという気がする今日この頃。
YAPC::Asia 2008 最高!
大岡山東工大キャンパスで行われたYAPC Asia 2008に参加してきました。今年はPerlのコミュニティに参加しはじめたばかりで、YAPCも初参加でした。
聞きたいセッッションが多すぎて本当にどれに出るのかはすごい悩むほどすごい内容で、すべてのセッションが本当に素晴らしく、全てが楽しかったです。話されている方、聞いている方、全員がとても楽しんでいる感じがとても伝わってきて、このようなコミュニティがYAPC Asiaを支えているのだなぁとも感じました。
このような素晴らしいカンファレンスに参加できて本当によかったと思います。カンファレンスを開催されたスタッフの方、スピーカーの方、スポンサーの方、本当にありがとうございました!
自分も一段とエネルギーをもらって、今年はCPAN Authorになるべく頑張ろりたいなと思ったのでした。Perlコミュニティ最高!
以下、参加したセッションで印象に残った点をメモとして書いてみました。
JavaScript::Writer - guogdさん
感想
PerlでJS生成的なHackについてでした。少し遅刻してしまったので、後で聞いてみようかなと思ってます。
FormValidator::Assets - typesterさん
内容のメモ
- Data::FormValidator, FormValidator::Simple, HTML::FormFuはDryじゃない
- 同じvalidation 項目を複数回書かないといけない
- そこで、inputフィールドのnameベースのバリデーション
- plaggerのEFTインスパイア.
- assetファイル
- field, filter, rule, bundle
感想
- サイトによっては何度も同じ項目がでてくるものもあるわけで、input fieldの名前ベースでのvalidationは理にかなっていて、coooool !
- asset定義がDSLっぽいのが個人的にとてもいいなぁと思いました。
- field, filter, ruleという構成は、柔軟に対応できてよさそうでした
- assetでいろんなルールが集まると、とても面白くなりそうでした
- plファイルっていうのも柔軟にvalidationのロジックが書けてよさそうでした
Getting Your Feed Even Wetter With XS - Disuke Makiさん
- XSはPerlとC言語をつなげるためのフレームワーク使える
- Perlで操作している「物」は全部Cの構造
- XSはCジェネレータ. 一部だけが微妙なPerl
- メモリ管理はReference Countingで行われる。
- REFCNT
- Object作ったり参照したりすると、REFCNTがあがったり下がったりする。
- SV
- 文字列、数値、レファレンス
- XSの前にSV
- SV
- SvPV文字列
- SvPPVIV
- 文字列、整数値など
- SVを操作するには、sv_setivなどのAPIがそろっている。
- SV以外にも変数がある、AV、HVなど
- HV (Hash Value)
- CとPerlを繋げるのがXS. Perlの代りにXSを書くなかれ。
- Cで書かれた物にPerlでアクセスするためだけに使う
- XS関数の定義
- シグネチャ
- XSセクション
- XSセクション
- ExtUtils::ParseXSツールによってCに展開される
- 例えばPREINTなどが展開される
- PREINT: 変数宣言に使う
- Xsubpp展開
- Typemap
- コード生成のイメージ
- Xsubpがtypemapとシグネチャなどをとってきて、cファイル生成
- typemapを定義する事によって、ほとんどコードを書く必要がなくなる。
- 組み込み済みのtypemapもある
- 面倒くさいPerlとCの変換はすべてtypemapが吸収してくれる
- GC
- PerlはREFCNTによるGC
- 一時変数は、sv_2mortal
- SvMAGIC
- TieもSvMagic
- TIPS
- 構造がわかっちゃえば、後はC.
- Profiler
感想
- CとPerlを繋げるのがXS. Perlの代りにXSを書くなかれ、といってたのが印象的
- ExtUtils::ParseXSツールによってCに展開された後の形をみえると理解は進みそう
- C <->Perlのデータ変換のためにTypemapを利用するというのが一つポイントだということがわかった
- REFCNTを完全に意識してコーディングするのはかなりノウハウがいりそう
- XSの話はあまり世間にでてきてないので、とても勉強になった!
IEコンテンツ自動判別によるXSS防止 - TAKESAKOさん
- HTML Escapeしてもダメなケースある
- multibyte xss attacks
- mod_waffulでセキュリティ対策
- 許される文字列を正規表現でできるようにする
- Errorページを返したりができる
- ApacheのFilter側でencodingもチェックする
感想
- mod_waffulがモジュールとして出ると、セキュリティ対策をアプリケーションと切り離して考えられるようになって、アプリケーション開発者が幸せになれる日がくるかもしれないなぁと思いました。
Introduction to DBIx::MoCo - naoyaさん
私的内容ハイライト
- 概要
- ActiveRecord
- Ruby-like list operations
- Transparent caching with Cache::*
- Test fixture
- 自分のリストクラスを使える to_json
- prefechの機能もある
- cacheはsessioを有効に
- cacheが有効に働かないケースがある
- Testing
感想
- 外部仕様はDODを少しシンプルにして、ActiveRecordからいくつかの機能をいれたような感じでした。いいとこどりしてある感じで、MOCOはとても使いやすそうでした
- 透過的なcachingができるようにしてScalabilityを確保できるようにしていると、RubyLikeにコード書けるのがとても綺麗に書けそうなのがいいなぁと
- sessionがどういうケースで必要なのかをもっと聞けるといいなぁと思いました
- 複雑なSQLを書きたい場合にどうするのかも興味があって、途中それっぽいスライドがあったのを理解していなかったかも
Perl Love for JavaScript Hackers - Ingy
私的内容ハイライト
感想
- Ingy productで多様されてるテクニック満載
- ほとんど知っていたというよりも、STが実際にやっていた内容でした
Improving your Catalyst Application - Jonathan Rockway
私的内容ハイライト
- Too much action
- テストできないからControllerにロジックいれるな
package MyApp::Controller::Foo;
use Moose;
BEGIN { extends 'Catalyst::Controller'}
- 次のバージョンのCatalystはMoose
- DBIx::Class
- MapMaker
- タグを簡単に
- DBICs::Deploy使えばtagsテーブルが作られる
- MapMaker
- Restricted resultsets
- databaseを壊さないようにするための仕組みがある
- Schema::RestrictWithObject
感想
- Catalyst使うとこんなに楽ができるよ!って内容で、プレゼンの流れがとても綺麗
- Logicの分離方法とかは大体思っていた内容
- Restricted resultsetを知らなかったので後で見てみる
Pathtrac - Kazuho Okuさん
私的内容ハイライト
- To Scale Out or Not
- CPUやストレージのコスト,アプリケーションによって
- Compression for size & speed
- 圧縮と高速化
- 高速なランダムアクセスが必要
- HDDはランダムアクセスが遅すぎる
- メモりで解析する必要あり.けど、メモリは高いから、データ圧縮は必要
- URLは圧縮可能
- KeyedMutex
- 同時に複数のクライアントから同じQueryが飛ばないようなことができる
- 単一サーバー上でデータをキャッシュッシュする
- Pathtraqの開発にはSQLが多い
- Filter::SQL
感想
古今東西ORマッパー - nekokakさん
私的内容ハイライト
- DOD
- Resultsetを扱う事も可能
- resultsets
- get_driverでわける
- Fey
- Dave RoiskyによるMooseベースのORマッパー
感想
- DBICがキャッシュしにくいっていうのは、色んな人が思っている共通の悩みなのだなぁということがわかったのは良かったです
- DOD::SQLは後で読んだ方がよさそうでした
- スケールさせたければDODのほうがキャッシュ綺麗に扱えて楽そう
- DBIC, DOD, Feyの中では、今後はDODに注目が集まりそうな気がしました
Gungho and cloud computing, a scalable crawling and processing framework - Jeff Kim
私的内容ハイライト
- Store raw HTML on S3
- Transfers between EC2 and S3 are quick and free.
- Hardwar Configuration
- Queueing/Messaging Server
- 1EC2 Extra-Large Instance
- Database Server
- 1EC2 Extra-Large Instance
- Gungho Cralers
- Queueing/Messaging Server
感想
2008-05-14
MapReduce::Lite
ithread |
![]()
http://d.hatena.ne.jp/naoya/20080511/1210506301
ithreadsを使っているコードをほとんど見た事がなかったので勉強になるなぁ。
MapReduceとは関係ないけれど、__PACKAGE__->meta->make_immutable; があったほうがBetterなケースのコードだと思った。この1行があるだけで、インスタンス生成が100倍早くなる。
# 実際のところ、インスタンスをRuntimeで作らなければいけない場合には、上記の1行がないと、遅くて使えない
DBIx::Class:Schema::Slave
dbic |
![]()
DBIx::Class:Schema::Slave について
http://hibinokoto.jp/archives/2008/05/post-263.html
Blog::Slaveのように書けばいいだけっていうのはDRYでいいかもしれないなぁ。今までは単にコネクションを分けるだけでいいんじゃないかと思っていたのだけれど、こっちのほうがずっと綺麗。
日記に書いておかないと忘れそうなのでメモ
2008-05-11
Class::MOPとattributeでAOP
Mooseのmethod_modifierはAOP的な仕組みではあるのですが、横断的な関心毎が特定クラスに密に結びついてしまうために、Separation of Concernsを実現するためには少しいまいちな仕様です
また、MooseのRoleにしてMixinできるようにしても、例えばmethod_modifierで指定する指定するメソッド名が、特定のクラスを意識することになるため、これもまたAOP的なSeparation of Concernsを実現するための仕組みとしては不十分です。Roleが、consumeする側のことしっているという点で、AOP的な関心ごとの分離とは少し違う仕組みだといえます。
横断的関心事を実装するAOPのAdviceは、対象となるクラスのことを知らないようにし、任意のクラスに適用できるになっているのが魅力です。これを実現する方法を考えてみました。Perlでは以下のようにやるのがよいのではないかと思っています。
- Adviceの指定する方法については、Perlのattributeでする
- いつどこにAdviceを適用するのかをPerlのAttributeで指定するということです
- Adviceのweavingは、DI Containerでする
- Adviceの処理でラップしたメソッドでそのクラスのメソッドを置き換える必要があるわけですが、それはDIコンテナにやらせます。
該当のクラスには、以下のように、いつどんなAdviceを適用するのかを、PerlのAttributeで指定させるのは、以下のようにします。JavaのAnnotationの代りにattributesを使います。
sub witdraw : Before(Debug) { }
Adviceは別クラスにして、完全にもとのクラスには依存しないようにさせます。そうすると、そのAdviceは任意のクラスに対して適用できるようになるため、AOP的なSeparation of Concernsが実現できます。ここの例では、AOP::Advice::Debugとしています。
DI ContainerでAdviceを適用させるわけですが、その理由は、DIコンテナにやらせることで、そのクラスはDIコンテナ外ではAdviceには依存しないPOPOになるからです。PerlのAttributeに処理を直接書いてしまうと、そのAttributeの処理を切り離すことが難しくなるため、横断的な関心ごとを対象のクラスから分離するのが難しくなります。単体テストをする際にも、横断的な関心ごとを分離してやる必要があります。
以下が、その実装例です。
#!/usr/bin/env perl use strict; use warnings; package Service; use Moose; use Data::Dumper; use attributes; use Attribute::Handlers; use Perl6::Say; has 'name' => ( 'is' => 'rw', default => sub {'service'} ); my %Attribute; sub MODIFY_CODE_ATTRIBUTES { my ( $class, $code_ref, @attribute ) = @_; $Attribute{$code_ref} = \@attribute; return; } sub FETCH_CODE_ATTRIBUTES { my ( $class, $code_ref ) = @_; return @{ $Attribute{$code_ref} || [] }; } sub Before : ATTR { } sub buisinessLogic : Before(Debug) { my ( $self, $args ) = @_; say '### BUSINESS LOGIC ###'; say $args; } # 横断的な関心事を切り離す。 package AOP::Advice::Debug; use Data::Dumper; use Perl6::Say; sub execute { my ( $self, $args ) = @_; say '### DEBUG ###'; say Dumper $args; } # DIContainerで横断的関心毎をWeavingする package DIContainer; use Perl6::Say; use Data::Dumper; sub weave_advices { my ( $class, $service ) = @_; my $method_map = $service->meta->get_method_map; foreach my $method_name ( keys %$method_map ) { my $method_code_ref = $method_map->{$method_name}->body; foreach my $attribute_name ( attributes::get($method_code_ref) ) { if ( $attribute_name =~ /^Before\((.*?)\)/ ) { my $type = $1; $class->weave_before_advice( $service, $method_name, $type ); } } } } sub weave_before_advice { my ( $class, $service, $method_name, $type ) = @_; if ( $type eq 'Debug' ) { $class->weave_log_before_advice( $service, $method_name ); } } sub weave_log_before_advice { my ( $class, $service, $method_name ) = @_; $service->meta->add_before_method_modifier( "$method_name" => AOP::Advice::Debug->can('execute') ); } sub main { my $service = Service->new; DIContainer->weave_advices($service); $service->buisinessLogic("Hello world"); } main();
実行すると、以下のようになります。ServiceのbusinessLogicメソッドを実行する前に、DebugのAdviceがCallされていることがわかりますね。DebugのAdviceは、対象のクラスに依存していないので、任意のクラスで使うことができます。これで、AOP的なSeparation of Concernsも実現できそうだということがわかります。
### DEBUG ### $VAR1 = 'Hello world'; ### BUSINESS LOGIC ### Hello world
DI Containerのところは、Bread::Boardに組み込んで使えるようにしてみようと思っています。Transactionのようにmethod単位で指定したいものや、TraceのInterceptorのようにパッケージ単位などで指定したいものなどもあると思うので、指定のさせ方はattribute以外にも複数用意できるようにしたいなとも思っています。
# というのを、PerlのattributeとClass::MOPを調べながら、Newbiethonで作ってみました。本当は、Bread::Boardに組み込むところまでもっていければよかったんですが、Bread::Boardのコードを読んでる途中で力尽きてしまいました。
2008-05-04
make_immutable
わかった。
use strict; use warnings; use Class::MOP; use Perl6::Say; my $yappo_meta = Class::MOP::Class->create( 'Yappo' => ( version => 0.01, methods => { holygrail => sub { say 'horygrail' } }, ), ); say '$yappo_meta : ' => $yappo_meta; # => Class::MOP::Class=HASH(0x882a70) my $yappo_class = $yappo_meta->construct_instance; say '$yappo_class->meta : ' => $yappo_class->meta; # => Class::MOP::Class=HASH(0x882a70) $yappo_class->meta->make_immutable; $yappo_class->meta->remove_method('holygrail');
CHI -- Unified cache interface
cpan |
![]()
http://search.cpan.org/~jswartz/CHI-0.07/lib/CHI.pm
cool!
DODのcacheの実装を見るとget_multi周りのcacheのAPIの共通化が上手くされていて、感動していたんですが、それを汎用化したような感じになってますね。
まだあまり使われていないみたいですが、これからはCHIを使っていくのが流行るかもしれないですね。
Mooseは実用で使えるか?
yusukbeeさんにmooseって実用で使えるかを聞かれる | benchmarkをとってみる | meta->make_immutableすれば、いけることがわかる | moose版catが全部そうなってるのを見る | http-engineを変更してみる | 間違って#http-engineに日本語でメッセージ | mstにmake_imuutableすんのは当たり前といわれる | 確かにmake_immutableすると早い | Mooseも実用でいけそう <- いまここ
nemuiからneru.
2008-05-03
複数のroleを満たしていることのチェック.
以下のような感じ.
my $type = type where { $_->does('Foo::Bar') && $_->does('Baz::Quux') && ... };
isa => $type
教えてもらった。もう少し上手く英語でかけると、正確に意図を伝えられるんだけどな。地道に。
perl programming with vim
よく使ってるのは、prove, perltidy, ファイル保存時のsyntax check(with perl-support)かなぁ。
書くときは、autocomplpop+ctags。これないとvimで書くのはしんどい。ファイル移動は、fuzzyfinder。
perlのftpluginは以下のような感じ.
http://github.com/dann/dotfiles/tree/master/.vim/ftplugin/perl.vim
" auto syntax check with Perl support au BufWritePost * call Perl_SyntaxCheck() | call Perl_SyntaxCheckMsg() | redraw! " prove noremap ,t <Esc>:!prv -lv t/%<CR> noremap ,T <Esc>:!prv -lv t/% \| less <CR> " perltidy noremap ,pt <Esc>:%! perltidy -pbp<CR> noremap ,ptv <Esc>:'<,'>! perltidy -pbp<CR>
Moose使うとコンパイルが遅いのかファイル保存時のsyntax checkを使うのは少しきつい。けど、コンパイルに失敗すると,ptでperltidyするときに困るから、どうしたもんかねと。
vimにもflymakeがあるといいなぁ. sav時にチェックってことがナンセンスな気がする。もっと、早い段階でチェックしたいんだなぁ。syntax checkと整形は人間がやるんじゃなくてツール側で勝手にやってほしいなぁと。
EclipseでやってるときはIDE側でリアルタイムでsyntax checkやって、SaveOnFormatプラグインでsav時に自動で整形ルールに従って整形されるから、人がそれらの作業をする必要がなくて、あれくらい楽になるといいんだけどなぁと。
あまりvim+perlな人をみないんだけれど、便利なtipsがあったら教えてほしい!emacs+perlな人はよくみるんだけれど。
Moose勉強するのに役立ったもの
この3つにMooseの使い方のエッセンスがつまっている気がした。
は殆ど同じ機能範囲で使ってる。
Devel::REPLのPluginとしてのRoleの使い方は少し特徴があるし面白い。Catalystの次期版のPlugin機構もおそらく似た形になる。
Reactionはキーワード作るところとType定義してるところが少し違う。
ReactionのMoose(+X)の使い方はもう少し勉強できるところがあるかも。
moose版Catalyst
http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Runtime/5.80/branches/moose/
runtimeの実行速度を高めるためにmake_immutableをしてるっていうのがわかる。さっきのベンチ結果とも一致してるなぁ。mod_perlとかで使うときには、これでClass::Accessor::Fastとも大差ないから、気にしなくてもいいかもね
プラグインはRoleになるってことで、Devel::REPL形式になりそうだなぁ
Mooseのパフォーマンス測定 Class::Accessor::Fast vs Moose
http://code2.0beta.co.uk/moose/svn/Moose/trunk/benchmarks/caf_vs_moose.pl
- setterは実行回数たりねーと怒られた.
- getterは大差なし
- インスタンス生成は、かなり差がある。最大100倍くらい遅い
- Destructionもかなり差がある
現状だとインスタンス作る場合には、mata->make_immutableしておいたほうがいいってこと。CGIで使うには無理がありそうだけど、そうじゃなきゃいけそうだなぁと。
DIコンテナでScopeをSingletonにしといて、startupタイミングでインスタンス作っとけば、実用上は問題ないかな。
hasとかで委譲したときに、どうなるかとかは測っておいたほうがいいかも。
SETTING
Benchmark: timing 100000 iterations of ClassAccessorFast, Moose, MooseImmutable, MooseImmutableNoConstructor...
ClassAccessorFast: 0.102277 wallclock secs ( 0.11 usr + 0.00 sys = 0.11 CPU) @ 909090.91/s (n=100000)
(warning: too few iterations for a reliable count)
Moose: 0.109756 wallclock secs ( 0.11 usr + 0.00 sys = 0.11 CPU) @ 909090.91/s (n=100000)
(warning: too few iterations for a reliable count)
MooseImmutable: 0.110045 wallclock secs ( 0.11 usr + 0.00 sys = 0.11 CPU) @ 909090.91/s (n=100000)
(warning: too few iterations for a reliable count)
MooseImmutableNoConstructor: 0.108017 wallclock secs ( 0.11 usr + 0.00 sys = 0.11 CPU) @ 909090.91/s (n=100000)
(warning: too few iterations for a reliable count)
Rate MooseImmutableNoConstructor MooseImmutable Moose ClassAccessorFast
MooseImmutableNoConstructor 909091/s -- 0% 0% -0%
MooseImmutable 909091/s 0% -- 0% -0%
Moose 909091/s 0% 0% -- -0%
ClassAccessorFast 909091/s 0% 0% 0% --
GETTING
Benchmark: timing 100000 iterations of ClassAccessorFast, Moose, MooseImmutable, MooseImmutableNoConstructor...
ClassAccessorFast: 0.0776682 wallclock secs ( 0.08 usr + 0.00 sys = 0.08 CPU) @ 1250000.00/s (n=100000)
(warning: too few iterations for a reliable count)
Moose: 0.0701921 wallclock secs ( 0.07 usr + 0.00 sys = 0.07 CPU) @ 1428571.43/s (n=100000)
(warning: too few iterations for a reliable count)
MooseImmutable: 0.0723972 wallclock secs ( 0.08 usr + 0.00 sys = 0.08 CPU) @ 1250000.00/s (n=100000)
(warning: too few iterations for a reliable count)
MooseImmutableNoConstructor: 0.0714548 wallclock secs ( 0.08 usr + 0.00 sys = 0.08 CPU) @ 1250000.00/s (n=100000)
(warning: too few iterations for a reliable count)
Rate MooseImmutable MooseImmutableNoConstructor ClassAccessorFast Moose
MooseImmutable 1250000/s -- -0% -0% -13%
MooseImmutableNoConstructor 1250000/s 0% -- 0% -12%
ClassAccessorFast 1250000/s 0% 0% -- -12%
Moose 1428571/s 14% 14% 14% --
CREATION
Benchmark: timing 100000 iterations of ClassAccessorFast, Moose, MooseImmutable, MooseImmutableNoConstructor...
ClassAccessorFast: 0.455661 wallclock secs ( 0.46 usr + 0.00 sys = 0.46 CPU) @ 217391.30/s (n=100000)
Moose: 50.7327 wallclock secs (50.71 usr + 0.03 sys = 50.74 CPU) @ 1970.83/s (n=100000)
MooseImmutable: 0.509074 wallclock secs ( 0.52 usr + 0.00 sys = 0.52 CPU) @ 192307.69/s (n=100000)
MooseImmutableNoConstructor: 7.42216 wallclock secs ( 7.41 usr + 0.01 sys = 7.42 CPU) @ 13477.09/s (n=100000)
Rate Moose MooseImmutableNoConstructor MooseImmutable ClassAccessorFast
Moose 1971/s -- -85% -99% -99%
MooseImmutableNoConstructor 13477/s 584% -- -93% -94%
MooseImmutable 192308/s 9658% 1327% -- -12%
ClassAccessorFast 217391/s 10930% 1513% 13% --
DESTRUCTION
Benchmark: timing 100000 iterations of ClassAccessorFast, Moose, MooseImmutable, MooseImmutableNoConstructor...
ClassAccessorFast: 0.0550349 wallclock secs ( 0.04 usr + 0.00 sys = 0.04 CPU) @ 2500000.00/s (n=100000)
(warning: too few iterations for a reliable count)
Moose: 0.299493 wallclock secs ( 0.30 usr + 0.00 sys = 0.30 CPU) @ 333333.33/s (n=100000)
(warning: too few iterations for a reliable count)
MooseImmutable: 0.149003 wallclock secs ( 0.16 usr + 0.00 sys = 0.16 CPU) @ 625000.00/s (n=100000)
(warning: too few iterations for a reliable count)
MooseImmutableNoConstructor: 0.142484 wallclock secs ( 0.14 usr + 0.00 sys = 0.14 CPU) @ 714285.71/s (n=100000)
(warning: too few iterations for a reliable count)
Rate Moose MooseImmutable MooseImmutableNoConstructor ClassAccessorFast
Moose 333333/s -- -47% -53% -87%
MooseImmutable 625000/s 87% -- -13% -75%
MooseImmutableNoConstructor 714286/s 114% 14% -- -71%
ClassAccessorFast 2500000/s 650% 300% 250% --
MooseX::App::Cmd
http://search.cpan.org/~nuffin/MooseX-App-Cmd/lib/MooseX/App/Cmd.pm
MooseX::Getopt + App::Cmd。これは明示的にオプションが書けていいなぁ。
opt_specの実装をするんじゃなくて、以下のように明示的にオプション設定を書く。
has blortex => (
isa => "Bool",
is => "rw",
cmd_aliases => "X",
documentation => "use the blortext algorithm",
);
これから分かることは、契約を明示したほうがわかりやすいものと組み合わせるのは、綺麗にかける可能性があって、そこにはDSL的な設定があうかもしれないってことかなぁ。
早速CLI用のベースクラスをこれに変えてみよう。
# ちょっと思ったのは、Validation系とMooseの組み合わせは結構相性がいいやもしれないなぁということ。
hasのrequired
moose |
![]()
これも仕様を明記するという点でいいなと思う。そのインスタンス変数が必須なのかオプショナルなのかっていうのが見れば分かる。
required => (1│0)
This marks the attribute as being required. This means a
defined value must be supplied during class construction, and
the attribute may never be set to "undef" with an accessor.
後はBread::BoardでDIするときにもいいかなぁと。このインスタンス変数にDIしわすれたとかいうのを防ぐことができる。
buildじゃなくてhasの+で上書き
moose |
![]()
hasの+でsubclassでdefaultを上書きできる。ってことで、実はbuildなくても殆どのケース困らない気がしてしまった。buildがどうしても必要になるケースってあんのかな。
メリットがあるとすれば、明示的にbuildだけを上書きすればいいっていうのがわかるってことくらいなのかなぁ。
package Foo; use Moose; has ’message’ => ( is => ’rw’, isa => ’Str’, default => ’Hello, I am a Foo’ ); package My::Foo; use Moose; extends ’Foo’; has ’+message’ => (default => ’Hello I am My::Foo’);
2008-05-02
WSGI
- Pylonsとその仲間たち
- http://groovie.org/articles/2006/09/18/wsgi-paste-pylons-and-all-that
- PEP333
- Rack
- http://chneukirchen.org/releases/rack-0.3.0.tar.gz
- Rackは小さいから読むのには丁度いいかも
middlewareのイメージがJavaのServletのFilterと同じなのかがまだよくわかってないけれど、少しイメージできてきた気も。
Catalystの次期版はMooseベース?
http://www.gossamer-threads.com/lists/catalyst/dev/18868
次期版はMooseベースになるのかぁ、これは自分にとってはいいなぁ。Moose使ったほうがモデルが楽にかけるし。これってcharsbarさんが、いってたReactionのことなのかなぁ。
プラグインの機構はRole+method_modifireの形になりそうだなぁ。Devel::REPLっぽい形になんのかな。
個人的には、Mooseを拡張して、キーワードを増やして、オレオレなDSLを作っていく方向には進んでほしくないなぁ。Mooseベースになってくれるのは、自然なシンタクスでかけるようになるからすごい嬉しいのだけれど。
# 次期版がMooseになると、この日記ももう少し続くかもしれないw
コラボレータのデフォルト値設定は基本builderで
moose |
![]()
defaultじゃなくて、builderを使おうという話。
要するにdeffaultでcoderefを書いてしまうと、サブクラスで違うものを使いにくいから、builder使って、sub classでbuilderのメソッドを上書きできるようにしようというもの。
If the default value is a simple scalar that only needs to be
calculated once (or a constant), use C<default>.
If the default value is an empty reference that needs to be wrapped in
a coderef like C, use C<default>.
Otherwise, use C<builder>.
This ensures that your classes are easily subclassable, and also helps
keep crufty code out of your attribute definition blocks.
MooseでDelegationを簡単
moose |
![]()
dmakiさんのコードを見て知ったのですが、handlesを使えばよいです.
package HTTP::Engine::Request; use Moose; use HTTP::Engine::Types::Request qw( Header ); use HTTP::Headers; has headers => ( is => 'rw', isa => 'Header', coerce => 1, default => sub { HTTP::Headers->new }, handles => [ qw(content_encoding content_length content_type header referer user_agent) ], ); ...
上記の例だとHTTP::Headersへ処理を委譲することができます。
上記の例のように、そのままのメソッド名でdelegationするのもできますが、Hashを渡すことで別名でdelegationすることもできます。
perldoc Mooseで、Hashの場合のdelegationの例が書いてあるので、それを見るのがよいです。
委譲するコードがとてもドライにかけるのでこれはよいですね。
Mooseでクラス属性
moose |
![]()
MooseX::ClassAttributeを使う
http://search.cpan.org/~drolsky/MooseX-ClassAttribute-0.04/lib/MooseX/ClassAttribute.pm
なんで、これMooseに標準で入ってないんだろうなぁ。
2008-05-01
YAPC::Asia
聞きたいものが多すぎる罠。YAPC::Asiaは両方いくのはちと難しそうだからどうするかなぁ。
MooseX::Types使って型定義
moose |
![]()
http://search.cpan.org/~phaylon/MooseX-Types-0.04/lib/MooseX/Types.pm
MooseX::Typesを使って、MyApp::Types::Core とか作ると、subtypeの定義を別のクラスに出すことができます。
型定義(subtype, coerce)は基本的に使いまわしたいもののはずなので、オレオレTypesを発展させて使いまわせるようにしておくと、使いどころが結構ありそうだなぁという気がします。
moose版のHTTP::Engineのほうも、Typesを別ディレクトリに分けてみました。もう少し型が増えれば、Typesの存在意義がでてくるんじゃないかと思います。あまり再利用がされなくても、クラス定義内にtype定義があるよりは、外に出したほうが美しいかなという気がするのでいいような気がしてます。
Devel::REPLでのプラグイン機構
MooseX::Object::Plaggableを使っていて、mixinの機構をPluginの機構として応用してるっていう点で面白いなぁと思う。で、さらにmixinする側にAOP的なフックを加えることで、Pluginの実行タイミングとフックポイントを決めている。
ただ、method modifireをフックポイントへの実行するコードの登録に結び付けているのは、もっと明示的なインターフェースのほうが美しいのかもしれないなぁ。
- どのフックポイントに
- どのタイミングで
- どんな処理を
ということを登録するインターフェースが明示的にあったほうがいいのかなと。要するに、上記のことを登録する関数がPluginのRoleとしてあったほうがいいのかなぁという気がする。
現状でも、MooseとRoleの仕組みをわかっていれば、Pluginは作れるんだけど、もう少し明示的なインターフェースのほうがいいのかもなぁという気もするという程度ではあるのだけれど。
Pluginの機構はもう少し色々とみてみよっと。
Perl+Java+Rubyな仕組みをMooseで
moose |
![]()
Rubyっぽく全てをオブジェクトとして扱えて、Javaっぽく制約をつけられて、Perlっぽくプラグインを増やせて、CPANで多くのライブラリも使えるというのが、自分の中で思っているいいとこ取りの理想の形態だなぁと思ってます。
Moose+autoboxで殆ど実現できるじゃん!ってところで、面白そうなところだなぁって思ってます。
Class::MOP++
autobox++
# パフォーマンス的にどうなるのかは気になるところですが、これはえろい人がチューニングしてくれるんじゃないかと。toyプロジェクトじゃないもので誰かが使えば結構流行るんじゃないかなぁ。
Mooseの気持ちいいところ
moose |
![]()
Mooseは、
- 自然にOOできる仕組み
- Java的にかっちり作る仕組み(interface+型による制約)
- meta programmingを簡単にできる仕組み(Perlの黒魔術的なコードから開放される)
- AOP的な横断的な関心毎を切り離す仕組み
があって、自然にコードを書けるのが気持ちいいなぁと思います。
AOPのadviceをMoose+Bread::Boardで
Mooseのmethod_modifireは、いわゆるAOPのadviceと同じで、before, after, arroundのadivceに対応するmethod_modifireが存在します。
Mooseの実装をみると、metaのmethod_modifireに登録してるだけなので(実際はMooseというよりも、Class::MOP使ってるだけ)、Mooseでクラスにaroundを直にかくっていう方法だけでなくて、もっと汎用的に使えそうです。
around => sub {
my $class = $CALLER;
return subname 'Moose::around' => sub (@&) {
my $code = pop @_;
my $meta = $class->meta;
$meta->add_around_method_modifier( $_, $code ) for @_;
};
},
Mooseを使って、aroundのkeywordを使って、直にクラスにarroundなどの定義をかいてしまうと、使える場所が限られてしまうのですが、これをRoleやクラスの実装から切り離すと、AOPと同じように、クラスの横断的な関心毎をクラスから切り離して扱うことが出来そうです。
実際には、以下のような感じでBread::Boardを拡張すれば使えそうです。
クラスをBread::Boardのサービスとして登録する際に、そのクラスのMethodのAttributeをみて、そのAttriubteがTransaction Attributeだったら、around method modifireとして、Transactionの開始終了を埋め込んだ実装を登録する
とすればよさそうです。
Mooseを使うと、Bread::BoardをベースにしたDIコンテナの仕組みも、より便利に使えそうですね。
MooseのMeta Attributeの仕組みはBread::Boardへのサービスの自動登録に使えそう!
Bread::Boardだと、以下のようにdependenciesを書かないといけないですが、この部分を独立したファイルに書くのは、個人的にはあまりよい方法ではないんじゃないかなぁと思います。
service ’application’ => (
class => ’MyApplication’,
dependencies => {
logger => depends_on(’logger’),
dbh => depends_on(’Database/dbh’),
}
);
何故、これがよくないかというと、冗長だからです。
Mooseで作るクラスでは、
package MyApplication; use Moose; has 'logger' ...
と記述するわけで、loggerに依存しているというのは、そのクラスをみればわかります。知りたいのは実装クラスが何か、要するにloggerを実装したクラスが何か?というのがだけがわかればよいわけです。
ですから、Bread::Boardのように記述するのではなくて、コンテナ側に登録するコードで書くのではなくて、injectされる側のAttributeに何をinjectするのかを明示させたほうがいいだろうなと思っています。
以下のようにして、Serviceの登録部分は自動でするというのが、いいんだろうなぁと思いました。
- lib/MyApp/Service/* をざっとなめて、serviceクラスをリストアップ
- dependenciesは、各クラスのhasに書かれたattributeからinjectしたい実装クラスをinject
Attributeの追加とあるAttributeのついたもの取得は、以下のCookbookにある方法でできることがわかりました。via yappo さんblog
http://search.cpan.org/~stevan/Moose/lib/Moose/Cookbook/Recipe21.pod
ということで、上記のことも実現できるじゃん!と思っていたのでした。Mooseかわいいよ、Moose。
Role+Method Modifiersによるプラグイン機構
Moose使って、Method Modifiersをクラスに直に埋め込んでしまうとあまり使いどころがなさそうだなぁと思っていたのだけれど、Roleのメソッドにくっつけて使うのを、id:tokuhiromさんが書いていて、これは面白いですね。
Devel::REPLのプラグインの機構から拝借してるとのことですが、なるほどなぁと思いました。プラグインの機構としてRoleとMethod Modifiersを使うのは面白いなぁと思いました。
Pluginのフックポイントに対して、どのタイミングでフックさせるのかをMethod Modifiersで指定させて、Roleではフックポイントにフックさせる実装を用意するという形です。
Moose::Roleの使い方のサンプルp
MooseのCookbookからRoleのInterfaceとしての役割を示すエッセンス部分を切り出してみました。
http://search.cpan.org/dist/Moose/lib/Moose/Cookbook/Recipe10.pod
#!/usr/bin/env perl use strict; use warnings; { package Comparable; use Moose::Role; requires 'compare'; sub equal_to { my ( $self, $other ) = @_; $self->compare($other) == 0; } } { package US::Currency; use Moose; with 'Comparable'; has 'amount' => ( is => 'rw', isa => 'Num', default => 0 ); sub compare { my ( $self, $other ) = @_; $self->amount <=> $other->amount; } } my $currency10 = US::Currency->new(amount => 10); my $currency20 = US::Currency->new(amount => 20); my $other_currency10 = US::Currency->new(amount =>10); warn $currency10->compare($currency20); #-1 warn $currency20->compare($currency10); #1 warn $currency10->equal_to($other_currency10); #1
Comparableというクラスが、Interfaceとしての役割を果たしていて、MooseのRoleになっています。このComparableを実装する人は、compareメソッドを実装しなければいけませんよというように読みます。(equal_toメソッドがcompareメソッドが実装されることを期待してます。)
Comparableを実装する具象クラスが、US::Currencyです。withというキーワードはMooseのキーワードで、JavaのImplementsみたいなものだと思ってください。要するに、このInterfaceを実装しますよということを明示します。このクラスで、compareメソッドを実装すると、equal_toメソッドも実装されます。
さて、これでcompareというメソッドを実装しない場合は、どうなるか試してましょう。compareをcompare2と名前を変えて、perl -wcでチェックすると、以下のようにcompare実装しろ!と怒られます。ちゃんと、Interfaceの役割として機能してますね。
'Comparable' requires the method 'compare' to be implemented by 'US::Currency'
今の記述では'filetype'がperlなバッファを開かれた際に各種設定が全バッファに対して有効になります。特に:autocmdは'filetype'がperlなバッファを開くたびに同じものが追加されていくのでバッファの保存時に同じ動作が複数回行われることになります。