Hatena::Groupcatalyst

dann@catalyst このページをアンテナに追加 RSSフィード

2008-05-25

Mooooooooooooooved

Mooooooooooooooved - dann@catalyst を含むブックマーク はてなブックマーク - Mooooooooooooooved - dann@catalyst Mooooooooooooooved - dann@catalyst のブックマークコメント

http://dann.g.hatena.ne.jp/dann/

Catalystで書く事がほとんどなくなったので、新しくグループを作成しました。Perl含めた雑多なネタは、上記のグループに書いていくことにします。

CatalystがMooseに移行したら、またこのグループでCatalystについて書いていこうと思ってます。

lzbnorlyiylzbnorlyiy2014/06/02 15:06ehaipdbubmztu, <a href="http://www.biukujldbe.com/">kqcwnissfq</a> , [url=http://www.wffjpdrlih.com/]liggqegyis[/url], http://www.uzxkbxozta.com/ kqcwnissfq

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080525

2008-05-20

コードは世界の共通言語

コードは世界の共通言語 - dann@catalyst を含むブックマーク はてなブックマーク - コードは世界の共通言語 - dann@catalyst コードは世界の共通言語 - dann@catalyst のブックマークコメント

コードを書いて示せば、いいねといってくれる世界があるからオープンソースの世界は面白い。コードが共通の言語になっている。英語がつたなくたって、課題とコードを書けば、それを評価してもらえる世界がある。

コードを介して言語を超えて色んな人と繋がれることができる。色んなレベルの楽しみがあると思うのだけれど、純粋に技術を介して、人と物を作るところに楽しさがあると思っている。

Perl Newbieなサイト

 Perl Newbieなサイト - dann@catalyst を含むブックマーク はてなブックマーク -  Perl Newbieなサイト - dann@catalyst  Perl Newbieなサイト - dann@catalyst のブックマークコメント

おぉ、cooooooooooooooool!id:yappo++

http://perl-users.jp/

newbie視点で色々と応援したいです!

ここ半年で色々と活動してみて、newbieでも飛び込んで何でもコードを書いてフィードバックをしてみたほうがいいなぁって思ってます。

脱newbieを目指して、KYせずに、色々とパッチを送ったり、いきなりhttp-engineのmoose化に関わってみたりとしてみてるわけですが、コミュニティにどんどん参加して、フィードバックをもらったほうが勉強になるし、何より楽しいです。

コードが汚かろうが美しかろうが、まずはアイデアとコードを書いてみて、コミュニティへのフィードバックしたほうが得られる物が大きい!コードかけなくたって疑問点があるだけだって、それだってフィードバックになりうると思って活動してます。

もっとPerlな人がnewbieであるなしかかわらず活動できる場があるといいなぁって思っていました。lazy-peopleはそんな場だったわけですが、こうやってperl-usersのような活動がもっと増えると、もっと色んな人が参加しやすくなって、色んな人がコミュニティを盛り上げていけるかもしれないですね。

Great!

# はてなに、perlerなgroupがあれば、すごいいいなぁと思ったり。

# はてなのグループじゃDISられるのかぁ。特定企業に結びついちゃうからなんですかねー

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080520

2008-05-19

Mooseのcommit bit

Mooseのcommit bit - dann@catalyst を含むブックマーク はてなブックマーク - Mooseのcommit bit - dann@catalyst Mooseのcommit bit - dann@catalyst のブックマークコメント

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の次期版はMooseベース@YAPC::Asia 2008 - dann@catalyst を含むブックマーク はてなブックマーク - Catalystの次期版はMooseベース@YAPC::Asia 2008 - dann@catalyst Catalystの次期版はMooseベース@YAPC::Asia 2008 - dann@catalyst のブックマークコメント

Catalystの話が全然ないじゃないか!とツッコミが入る今日この頃なので、Catalystについて書いておきます。

YAPC::Asia2008でCatalystの次期版はMooseベースだよ!とjrockwayのセッションでいっていたことでしょうか。言及はされませんでしたが、PluginはおそらくMooseのRoleをベースにしたDevel::REPL形式のプラグイン方式になるんじゃないかと思います。

Mooooooooooooooooooose!

# 既存のプラグインがどうなるのかは気になるところですね。雰囲気的には後方互換性が切れてしまう気もするんですが、どうなるんでしょうね。

xynswzhyplxynswzhypl2014/03/18 16:21ybjuwdbubmztu, <a href="http://www.jumycxtcnp.com/">zeelgkztvt</a> , [url=http://www.kyohknmoql.com/]oslendiqvk[/url], http://www.dajygpsjyq.com/ zeelgkztvt

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080519

2008-05-18

MooseのRoleでAOP

|  MooseのRoleでAOP  - dann@catalyst を含むブックマーク はてなブックマーク -  MooseのRoleでAOP  - dann@catalyst  MooseのRoleでAOP  - dann@catalyst のブックマークコメント

aroundのキーワードで指定できるメソッドが1つになってしまうからAOP目的では使えないけれど、around 'do_*' のように指定できるようになれば、Roleを複数のクラスに組み込めて使えるようになる。

だから、Transactionのように明示的にメソッドを指定したい場合には、aroundのmodifierにメソッドを登録するところを少し書き換えるだけでいけると思う。Mooseにパッチあてたいなぁ、これは。

package指定のようなjoinpointの指定はできないけれど、実際にパッケージ指定みたいなので使う場面はログ系くらしかないので、無くても困らないかもしれない。

で、実際、DIコンテナでweavingするよりも、こっちのほうが現実的かなぁという気がする今日この頃。

YAPC::Asia 2008 最高!

 YAPC::Asia 2008 最高! - dann@catalyst を含むブックマーク はてなブックマーク -  YAPC::Asia 2008 最高! - dann@catalyst  YAPC::Asia 2008 最高! - dann@catalyst のブックマークコメント

大岡山東工大キャンパスで行われたYAPC Asia 2008に参加してきました。今年はPerlのコミュニティに参加しはじめたばかりで、YAPCも初参加でした。

聞きたいセッッションが多すぎて本当にどれに出るのかはすごい悩むほどすごい内容で、すべてのセッションが本当に素晴らしく、全てが楽しかったです。話されている方、聞いている方、全員がとても楽しんでいる感じがとても伝わってきて、このようなコミュニティがYAPC Asiaを支えているのだなぁとも感じました。

このような素晴らしいカンファレンスに参加できて本当によかったと思います。カンファレンスを開催されたスタッフの方、スピーカーの方、スポンサーの方、本当にありがとうございました!

自分も一段とエネルギーをもらって、今年はCPAN Authorになるべく頑張ろりたいなと思ったのでした。Perlコミュニティ最高!

以下、参加したセッションで印象に残った点をメモとして書いてみました。

JavaScript::Writer - guogdさん

感想

PerlJS生成的なHackについてでした。少し遅刻してしまったので、後で聞いてみようかなと思ってます。

FormValidator::Assets - typesterさん

内容のメモ
  • Data::FormValidator, FormValidator::Simple, HTML::FormFuはDryじゃない
    • 同じvalidation 項目を複数回書かないといけない
  • そこで、inputフィールドのnameベースのバリデーション
  • plaggerEFTインスパイア.
    • 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)
    • SVの中身を取得したり、SVの中身のチェックなどは、SvOKなどのマクロがある。
  • CとPerlを繋げるのがXS. Perlの代りにXSを書くなかれ。
  • Cで書かれた物にPerlでアクセスするためだけに使う
  • XS関数の定義
    • シグネチャ
    • XSセクション
  • XSセクション
    • ExtUtils::ParseXSツールによってCに展開される
    • 例えばPREINTなどが展開される
  • PREINT: 変数宣言に使う
  • Xsubpp展開
  • Typemap
    • C型をPerlで表する.Perl型C型への変換.毎回必要な作業
    • それをするための仕組みがTypemap
  • コード生成のイメージ
    • Xsubpがtypemapとシグネチャなどをとってきて、cファイル生成
    • typemapを定義する事によって、ほとんどコードを書く必要がなくなる。
    • 組み込み済みのtypemapもある
    • 面倒くさいPerlとCの変換はすべてtypemapが吸収してくれる
  • GC
    • GCのタイミング
      • ランタイム中のGC
      • OPとOPの間
    • プログラム終了時
      • GC周りがはまりやすい
  • PerlはREFCNTによるGC
    • DESTROYが呼ばれるタイミングが必ず保証されている
    • XSではREFCNTを手動操作できるが、自動的にREFCNTが+されてしまうPerl APIを呼ぶと、すべての参照を消してもREFCNTが1のまま.メモリーリーク
  • 一時変数は、sv_2mortal
  • SvMAGIC
    • Perl内部の黒魔法
    • SVに任意の「何か」をくっつけられる
    • データ、コールバックなど何でも
    • SVにMAGICというスロットが増えていて、
      • MAGIC
        • typeでどんな魔法をかけるか
        • objectにデータ構造を格納
  • TieもSvMagic
  • TIPS
    • SvOK推奨
    • こまめにSvOKで値がundefかどうかチェック
    • HVとかAVの操作はしないほうがよい
      • Perl側で処理して、SVでわたしたほうがよい
    • UTF8 - XSでいじらない
  • 構造がわかっちゃえば、後はC.
  • Profiler
    • MAKEFILE.PLに--debuging -gをコンパイルできるようにする
    • GProfはダメ
    • debugはgdb, vargrindをほうがいい
感想
  • 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さん

私的内容ハイライト
  • 概要
  • 自分のリストクラスを使える to_json
  • prefechの機能もある
  • cacheはsessioを有効に
    • cacheが有効に働かないケースがある
  • Testing
    • YAMLでFixtureを使えるようになっている。
    • YAMLにbug idなどを書いて、それようのYAMLデータを書いて、テストを追加するなどの使い方

感想

  • 外部仕様は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
    • REST action使う
    • GET, POSTの分岐 - REST action使うか
  • テストできないからControllerにロジックいれるな
    • Catalyst::Model::Adaptor
    • Catalyst::Model::Adaptorのprepare_argumentsで事前にコレボレータを渡してLogicに処理委譲
  package MyApp::Controller::Foo;
  use Moose;
  BEGIN { extends 'Catalyst::Controller'}
  • 次のバージョンのCatalystはMoose
  • DBIx::Class
    • MapMaker
      • タグを簡単に
      • DBICs::Deploy使えばtagsテーブルが作られる
  • Restricted resultsets
    • databaseを壊さないようにするための仕組みがある
    • Schema::RestrictWithObject
感想
  • Catalyst使うとこんなに楽ができるよ!って内容で、プレゼンの流れがとても綺麗
  • Logicの分離方法とかは大体思っていた内容
  • Restricted resultsetを知らなかったので後で見てみる

Pathtrac - Kazuho Okuさん

私的内容ハイライト
  • To Scale Out or Not
    • CPUやストレージのコスト,アプリケーションによって
  • Compression for size & speed
    • 圧縮と高速化
  • 高速なランダムアクセスが必要
    • HDDはランダムアクセスが遅すぎる
    • メモりで解析する必要あり.けど、メモリは高いから、データ圧縮は必要
  • URLは圧縮可能
    • gzipなどは圧縮には使いにくい
    • 事前知識を利用した圧縮が必要
      • URL Compression: Static PPM (Prediction by Partitial Matching)
      • Use range corder as backend
    • URLの圧縮はcodereposに挙っている
      • MySQLのUFDとして実装
    • 圧縮したほうがデータサイズが小さくなるので、高速になる
    • Range Coderは展開速度が遅いので、SSEで最適化
  • KeyedMutex
    • 同時に複数のクライアントから同じQueryが飛ばないようなことができる
    • 単一サーバー上でデータをキャッシュッシュする
  • Pathtraqの開発にはSQLが多い
感想
  • 明らかにほかの人とレイヤが違って、とても面白かったです
  • URLの圧縮というのが凄まじい圧縮率で驚きました。URLは何かとよく使いそうなデータなので、ほかでも使えるところがありそうですね、

古今東西ORマッパー - nekokakさん

私的内容ハイライト

DBIC/DOD/Feyの紹介

  • DOD
    • Resultsetを扱う事も可能
    • resultsets
  • get_driverでわける
    • 独自にpartition
    • DBICなどに比べてコンパクト
    • Cacheが簡単に使えてウマー
    • Partitionも簡単に使える
  • 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
感想
  • dmakiさんのblogでどんな構成か大体しっていたので、構成として面白いところはなかったのですが、EC2,S3を使ったコスト削減の話がとても面白かったです
  • EC2でクローラ動かして、S3でHTML保存という使い方は面白いなぁと思いました
  • 必要なときに必要なだけのEC2インスタンスを動かすというのは、とても魅力的で今後もっと使われていくだろうなと思いました

SausanSausan2012/07/22 03:08That's an apt asnewr to an interesting question

anffdvuzfokanffdvuzfok2012/07/22 19:26SnO9c2 <a href="http://nzylyqfxwrpo.com/">nzylyqfxwrpo</a>

gkortwsgkortws2012/07/23 09:12h7HQQi , [url=http://bbbhbdzycttv.com/]bbbhbdzycttv[/url], [link=http://rnggguldzngk.com/]rnggguldzngk[/link], http://wzokbsjxqcvn.com/

odysrqkoodysrqko2012/07/24 08:40pwUvtl <a href="http://xocfinihwmxt.com/">xocfinihwmxt</a>

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080518

2008-05-14

MapReduce::Lite

|  MapReduce::Lite - dann@catalyst を含むブックマーク はてなブックマーク -  MapReduce::Lite - dann@catalyst  MapReduce::Lite - dann@catalyst のブックマークコメント

http://d.hatena.ne.jp/naoya/20080511/1210506301

ithreadsを使っているコードをほとんど見た事がなかったので勉強になるなぁ。

MapReduceとは関係ないけれど、__PACKAGE__->meta->make_immutable; があったほうがBetterなケースのコードだと思った。この1行があるだけで、インスタンス生成が100倍早くなる。

# 実際のところ、インスタンスをRuntimeで作らなければいけない場合には、上記の1行がないと、遅くて使えない

DBIx::Class:Schema::Slave

|  DBIx::Class:Schema::Slave - dann@catalyst を含むブックマーク はてなブックマーク -  DBIx::Class:Schema::Slave - dann@catalyst  DBIx::Class:Schema::Slave - dann@catalyst のブックマークコメント

DBIx::Class:Schema::Slave について

http://hibinokoto.jp/archives/2008/05/post-263.html

Blog::Slaveのように書けばいいだけっていうのはDRYでいいかもしれないなぁ。今までは単にコネクションを分けるだけでいいんじゃないかと思っていたのだけれど、こっちのほうがずっと綺麗。

日記に書いておかないと忘れそうなのでメモ

oiouxfawoiouxfaw2011/03/24 05:26SPSwuq <a href="http://chdglodetxpl.com/">chdglodetxpl</a>, [url=http://vrjfkcyyoxop.com/]vrjfkcyyoxop[/url], [link=http://dgfqtusveujx.com/]dgfqtusveujx[/link], http://pcdbfdvwdlgt.com/

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080514

2008-05-11

MacBook買いました!

MacBook買いました! - dann@catalyst を含むブックマーク はてなブックマーク - MacBook買いました! - dann@catalyst MacBook買いました! - dann@catalyst のブックマークコメント

switch中!後で書く!

Class::MOPとattributeでAOP

Class::MOPとattributeでAOP - dann@catalyst を含むブックマーク はてなブックマーク - Class::MOPとattributeでAOP - dann@catalyst Class::MOPとattributeでAOP - dann@catalyst のブックマークコメント

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のコードを読んでる途中で力尽きてしまいました。

http://d.hatena.ne.jp/tomyhero/20080503/1209830387

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080511

2008-05-04

make_immutable

make_immutable - dann@catalyst を含むブックマーク はてなブックマーク - make_immutable - dann@catalyst make_immutable - dann@catalyst のブックマークコメント

わかった。

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

|  CHI -- Unified cache interface - dann@catalyst を含むブックマーク はてなブックマーク -  CHI -- Unified cache interface - dann@catalyst  CHI -- Unified cache interface - dann@catalyst のブックマークコメント

http://search.cpan.org/~jswartz/CHI-0.07/lib/CHI.pm

cool!

DODcacheの実装を見るとget_multi周りのcacheAPIの共通化が上手くされていて、感動していたんですが、それを汎用化したような感じになってますね。

まだあまり使われていないみたいですが、これからはCHIを使っていくのが流行るかもしれないですね。

Mooseは実用で使えるか?

Mooseは実用で使えるか? - dann@catalyst を含むブックマーク はてなブックマーク - Mooseは実用で使えるか? - dann@catalyst Mooseは実用で使えるか? - dann@catalyst のブックマークコメント

yusukbeeさんにmooseって実用で使えるかを聞かれる
 |
benchmarkをとってみる
 |
meta->make_immutableすれば、いけることがわかる
 |
moose版catが全部そうなってるのを見る
 |
http-engineを変更してみる
 |
間違って#http-engineに日本語でメッセージ
 |
mstにmake_imuutableすんのは当たり前といわれる
 |
確かにmake_immutableすると早い
 |
Mooseも実用でいけそう <- いまここ

nemuiからneru.

2008-05-03

複数のroleを満たしていることのチェック.

複数のroleを満たしていることのチェック. - dann@catalyst を含むブックマーク はてなブックマーク - 複数のroleを満たしていることのチェック. - dann@catalyst 複数のroleを満たしていることのチェック. - dann@catalyst のブックマークコメント

以下のような感じ.

my $type = type where { $_->does('Foo::Bar') && $_->does('Baz::Quux') && ... };

isa => $type

教えてもらった。もう少し上手く英語でかけると、正確に意図を伝えられるんだけどな。地道に。

perl programming with vim

perl programming with vim - dann@catalyst を含むブックマーク はてなブックマーク - perl programming with vim - dann@catalyst perl programming with vim - dann@catalyst のブックマークコメント

よく使ってるのは、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な人はよくみるんだけれど。

# flymake, yasnippet, anything をvimにも!

Moose勉強するのに役立ったもの

Moose勉強するのに役立ったもの - dann@catalyst を含むブックマーク はてなブックマーク - Moose勉強するのに役立ったもの - dann@catalyst Moose勉強するのに役立ったもの - dann@catalyst のブックマークコメント

この3つにMooseの使い方のエッセンスがつまっている気がした。

は殆ど同じ機能範囲で使ってる。

Devel::REPLのPluginとしてのRoleの使い方は少し特徴があるし面白い。Catalystの次期版のPlugin機構もおそらく似た形になる。

Reactionはキーワード作るところとType定義してるところが少し違う。

ReactionのMoose(+X)の使い方はもう少し勉強できるところがあるかも。

moose版Catalyst

moose版Catalyst - dann@catalyst を含むブックマーク はてなブックマーク - moose版Catalyst - dann@catalyst moose版Catalyst - dann@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

Mooseのパフォーマンス測定 Class::Accessor::Fast vs Moose - dann@catalyst を含むブックマーク はてなブックマーク - Mooseのパフォーマンス測定 Class::Accessor::Fast vs Moose - dann@catalyst Mooseのパフォーマンス測定 Class::Accessor::Fast vs Moose - dann@catalyst のブックマークコメント

http://code2.0beta.co.uk/moose/svn/Moose/trunk/benchmarks/caf_vs_moose.pl

  • setterは実行回数たりねーと怒られた.
  • getterは大差なし
  • インスタンス生成は、かなり差がある。最大100倍くらい遅い
  • Destructionもかなり差がある

現状だとインスタンス作る場合には、mata->make_immutableしておいたほうがいいってこと。CGIで使うには無理がありそうだけど、そうじゃなきゃいけそうだなぁと。

DIコンテナでScopeSingletonにしといて、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

MooseX::App::Cmd - dann@catalyst を含むブックマーク はてなブックマーク - MooseX::App::Cmd - dann@catalyst MooseX::App::Cmd - dann@catalyst のブックマークコメント

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

|  hasのrequired - dann@catalyst を含むブックマーク はてなブックマーク -  hasのrequired - dann@catalyst  hasのrequired - dann@catalyst のブックマークコメント

これも仕様を明記するという点でいいなと思う。そのインスタンス変数が必須なのかオプショナルなのかっていうのが見れば分かる。

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の+で上書き

|  buildじゃなくてhasの+で上書き - dann@catalyst を含むブックマーク はてなブックマーク -  buildじゃなくてhasの+で上書き - dann@catalyst  buildじゃなくてhasの+で上書き - dann@catalyst のブックマークコメント

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’);

ka-nachtka-nacht2008/05/04 23:11ftpluginにしているならば:autocmdのパターンは*でなく<buffer>を指定し、各種:mapには<buffer>を指定すべきです。
今の記述では'filetype'がperlなバッファを開かれた際に各種設定が全バッファに対して有効になります。特に:autocmdは'filetype'がperlなバッファを開くたびに同じものが追加されていくのでバッファの保存時に同じ動作が複数回行われることになります。

danndann2008/05/05 02:29おぉ、ありがとうございます。

SevenSeven2011/12/30 11:35Good to see real expertise on dipslay. Your contribution is most welcome.

lnuadjvlnuadjv2011/12/30 19:298VZuNg <a href="http://xdgfwxgfsesx.com/">xdgfwxgfsesx</a>

atabaoatabao2011/12/31 22:27AejGt0 , [url=http://jzqszuxdfpva.com/]jzqszuxdfpva[/url], [link=http://qadlawxatmqq.com/]qadlawxatmqq[/link], http://udyntwmlzejv.com/

iumuxzhfiumuxzhf2012/01/02 02:59NXCef8 , [url=http://bqzxitpxnvhn.com/]bqzxitpxnvhn[/url], [link=http://khtunmodqxym.com/]khtunmodqxym[/link], http://iovvsttbnacz.com/

2008-05-02

WSGI

WSGI - dann@catalyst を含むブックマーク はてなブックマーク - WSGI - dann@catalyst WSGI - dann@catalyst のブックマークコメント

middlewareのイメージがJavaServletのFilterと同じなのかがまだよくわかってないけれど、少しイメージできてきた気も。

Catalystの次期版はMooseベース?

Catalystの次期版はMooseベース? - dann@catalyst を含むブックマーク はてなブックマーク - Catalystの次期版はMooseベース? - dann@catalyst Catalystの次期版はMooseベース? - dann@catalyst のブックマークコメント

catalyst-devのMLから

http://www.gossamer-threads.com/lists/catalyst/dev/18868

次期版はMooseベースになるのかぁ、これは自分にとってはいいなぁ。Moose使ったほうがモデルが楽にかけるし。これってcharsbarさんが、いってたReactionのことなのかなぁ。

プラグインの機構はRole+method_modifireの形になりそうだなぁ。Devel::REPLっぽい形になんのかな。

個人的には、Mooseを拡張して、キーワードを増やして、オレオレなDSLを作っていく方向には進んでほしくないなぁ。Mooseベースになってくれるのは、自然なシンタクスでかけるようになるからすごい嬉しいのだけれど。

# 次期版がMooseになると、この日記ももう少し続くかもしれないw

コラボレータのデフォルト値設定は基本builderで

|  コラボレータのデフォルト値設定は基本builderで - dann@catalyst を含むブックマーク はてなブックマーク -  コラボレータのデフォルト値設定は基本builderで - dann@catalyst  コラボレータのデフォルト値設定は基本builderで - dann@catalyst のブックマークコメント

defaultじゃなくて、builderを使おうという話。

http://code2.0beta.co.uk/moose/svnweb/index.cgi/moose/view/Moose/trunk/lib/Moose/Cookbook/Recipe9.pod

要するに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でDelegationを簡単 - dann@catalyst を含むブックマーク はてなブックマーク - MooseでDelegationを簡単 - dann@catalyst MooseでDelegationを簡単 - dann@catalyst のブックマークコメント

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でクラス属性 - dann@catalyst を含むブックマーク はてなブックマーク - Mooseでクラス属性 - dann@catalyst Mooseでクラス属性 - dann@catalyst のブックマークコメント

MooseX::ClassAttributeを使う

http://search.cpan.org/~drolsky/MooseX-ClassAttribute-0.04/lib/MooseX/ClassAttribute.pm

なんで、これMooseに標準で入ってないんだろうなぁ。

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080502

2008-05-01

YAPC::Asia

YAPC::Asia - dann@catalyst を含むブックマーク はてなブックマーク - YAPC::Asia - dann@catalyst YAPC::Asia - dann@catalyst のブックマークコメント

聞きたいものが多すぎる罠。YAPC::Asiaは両方いくのはちと難しそうだからどうするかなぁ。

http://conferences.yapcasia.org/ya2008/schedule

MooseX::Types使って型定義

|  MooseX::Types使って型定義 - dann@catalyst を含むブックマーク はてなブックマーク -  MooseX::Types使って型定義 - dann@catalyst  MooseX::Types使って型定義 - dann@catalyst のブックマークコメント

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でのプラグイン機構

Devel::REPLでのプラグイン機構 - dann@catalyst を含むブックマーク はてなブックマーク - Devel::REPLでのプラグイン機構 - dann@catalyst Devel::REPLでのプラグイン機構 - dann@catalyst のブックマークコメント

MooseX::Object::Plaggableを使っていて、mixinの機構をPluginの機構として応用してるっていう点で面白いなぁと思う。で、さらにmixinする側にAOP的なフックを加えることで、Pluginの実行タイミングとフックポイントを決めている。

ただ、method modifireをフックポイントへの実行するコードの登録に結び付けているのは、もっと明示的なインターフェースのほうが美しいのかもしれないなぁ。

  • どのフックポイントに
  • どのタイミングで
  • どんな処理を

ということを登録するインターフェースが明示的にあったほうがいいのかなと。要するに、上記のことを登録する関数がPluginのRoleとしてあったほうがいいのかなぁという気がする。

現状でも、MooseとRoleの仕組みをわかっていれば、Pluginは作れるんだけど、もう少し明示的なインターフェースのほうがいいのかもなぁという気もするという程度ではあるのだけれど。

Pluginの機構はもう少し色々とみてみよっと。

Perl+Java+Rubyな仕組みをMooseで

|  Perl+Java+Rubyな仕組みをMooseで - dann@catalyst を含むブックマーク はてなブックマーク -  Perl+Java+Rubyな仕組みをMooseで - dann@catalyst  Perl+Java+Rubyな仕組みをMooseで - dann@catalyst のブックマークコメント

Rubyっぽく全てをオブジェクトとして扱えて、Javaっぽく制約をつけられて、Perlっぽくプラグインを増やせて、CPANで多くのライブラリも使えるというのが、自分の中で思っているいいとこ取りの理想の形態だなぁと思ってます。

Moose+autoboxで殆ど実現できるじゃん!ってところで、面白そうなところだなぁって思ってます。

Class::MOP++

autobox++

# パフォーマンス的にどうなるのかは気になるところですが、これはえろい人がチューニングしてくれるんじゃないかと。toyプロジェクトじゃないもので誰かが使えば結構流行るんじゃないかなぁ。

Mooseの気持ちいいところ

|  Mooseの気持ちいいところ - dann@catalyst を含むブックマーク はてなブックマーク -  Mooseの気持ちいいところ - dann@catalyst  Mooseの気持ちいいところ - dann@catalyst のブックマークコメント

Mooseは、

  • 自然にOOできる仕組み
  • Java的にかっちり作る仕組み(interface+型による制約)
  • meta programmingを簡単にできる仕組み(Perlの黒魔術的なコードから開放される)
  • AOP的な横断的な関心毎を切り離す仕組み

があって、自然にコードを書けるのが気持ちいいなぁと思います。

AOPのadviceをMoose+Bread::Boardで

AOPのadviceをMoose+Bread::Boardで - dann@catalyst を含むブックマーク はてなブックマーク - AOPのadviceをMoose+Bread::Boardで - dann@catalyst AOPのadviceをMoose+Bread::Boardで - dann@catalyst のブックマークコメント

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へのサービスの自動登録に使えそう!

MooseのMeta Attributeの仕組みはBread::Boardへのサービスの自動登録に使えそう! - dann@catalyst を含むブックマーク はてなブックマーク - MooseのMeta Attributeの仕組みはBread::Boardへのサービスの自動登録に使えそう! - dann@catalyst MooseのMeta Attributeの仕組みはBread::Boardへのサービスの自動登録に使えそう! - dann@catalyst のブックマークコメント

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によるプラグイン機構

Role+Method Modifiersによるプラグイン機構 - dann@catalyst を含むブックマーク はてなブックマーク - Role+Method Modifiersによるプラグイン機構 - dann@catalyst Role+Method Modifiersによるプラグイン機構 - dann@catalyst のブックマークコメント

Moose使って、Method Modifiersをクラスに直に埋め込んでしまうとあまり使いどころがなさそうだなぁと思っていたのだけれど、Roleのメソッドにくっつけて使うのを、id:tokuhiromさんが書いていて、これは面白いですね。

Devel::REPLのプラグインの機構から拝借してるとのことですが、なるほどなぁと思いました。プラグインの機構としてRoleとMethod Modifiersを使うのは面白いなぁと思いました。

Pluginのフックポイントに対して、どのタイミングでフックさせるのかをMethod Modifiersで指定させて、Roleではフックポイントにフックさせる実装を用意するという形です。

Moose::Roleの使い方のサンプルp

Moose::Roleの使い方のサンプルp - dann@catalyst を含むブックマーク はてなブックマーク - Moose::Roleの使い方のサンプルp - dann@catalyst Moose::Roleの使い方のサンプルp - dann@catalyst のブックマークコメント

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'