Jensen_Interceptor_III

NOTE(2020/09/03): この記事は2013年に書かれており、古い内容になっています。現在のGroovyの実装と異なる場合があります。

いつも、PHPのことを話している人と思っているだろう。
実は、現在の大半のお仕事は Groovy によって行われているのだよ。

ブログでは初の Groovy ネタです。1年ほど、Groovy を触っているのですが、
私のような PHPer でも (一応、Javaの経験は昔にある) すんなり触ることができる
素晴らしい言語です。

大体のことは、プログラミングGroovy で学べました。
良い本です。

今回は、Groovy の Interception についてメモです。

NOTE (2020/09/03): Groovyをホスティングしていた、Codehaus が2015年にサービス終了してしまったために、リンク切れとなっていました。現在のGroovyドキュメントに当該の記述が見つからなかったため、参考リンクとして以下を貼ります。
Internet Archive へのリンク
Interceptor のテストコード
API Doc (Interceptor)

Interception と言えば、Spring Framework なんかにある、特定のメソッドの
実行前と、実行後に何らかのロジックを仕込むアイツです。
PHP で言えば、BEAR.Sunday が、この機構を見事に持ってます。

AOP 的には、本質 (実際のロジック) でない横断的な関心事 (実行時間計測・ロギング)
は、本質とは別に実装せよ。とのことらしいです。

というわけで、実際のコードを確認。

まずは、こんなコードを用意して、GroovyConsole あたりで実行してみましょう。

class Hello {
  def name
  Hello(def name) {
    this.name = name
  }
  void sayHello() {
    println "Hello, ${name}."
  }
}

def h = new Hello("bucyou")
h.sayHello() // Hello, bucyou.

この、クラスに対して、Interceptor を差し込みます。

class Hello {
  def name
  Hello(def name) {
    this.name = name
  }
  void sayHello() {
    println "Hello, ${name}."
  }
}

class MyInterceptor implements Interceptor {
  // 前処理
  Object beforeInvoke(Object object, String methodName, Object[] argments) {
    println "beforeInvoke ${methodName}"

    null
  }

  // 自動的にメソッドを invoke する場合は true
  boolean doInvoke() { true }

  // 後処理 メソッド実行の結果を result で改変できる
  Object afterInvoke(Object object, String methodName, Object[] argments, Object result) {
    println "afterInvoke ${methodName}"

    result
  }
}

def proxy = ProxyMetaClass.getInstance(Hello);
proxy.interceptor = new MyInterceptor();

// ここは interceptor による割り込みはない
def h1 = new Hello("bucyou");
h1.sayHello();

// use を使った部分だけ interceptor により割り込み有り
proxy.use {
    def h2 = new Hello("bucyou2");
    h2.sayHello() // Hello, bucyou.
}

そうすると、出力結果としては

Hello, bucyou.
beforeInvoke ctor
afterInvoke ctor
beforeInvoke sayHello
beforeInvoke println
Hello, bucyou2.
afterInvoke println
afterInvoke sayHello

となります。メソッド名で振り分けているわけではないので、コンストラクタや
println() でも、beforeInvoke, afterInvoke が走っています。
Advisor 的なものを作れば、Groovy 単体で、十分に機能する Interceptor
実装が出来るかもしれません。

お久しぶりです。Ooharabucyou でございます。
当ブログの存在をすっかり忘却しておりましたが、みなさまお元気でしょうか。

最近は、本業ではもっぱら GroovyGradle と戯れる日々なので
PHP については、暫く触っていませんでしたが、
PHPMatsuri も近づいておりますので、201千葉コーワーキングにこもり
こうして準備をしているわけでございます。

さてさて、久しぶりの話題は composer でございます。
去年の PHPConference などでも、以下の様な話題で composer の
布教活動などをしました。

あれから、10ヶ月。Github に composer が登場してから、まもなく2年となろうとしております。
PHP勉強会などに参加すると、だいぶ普及してきたように思えます。
Symfony だけでなく、様々なプロジェクトで活用されている成果なのでしょう。

pear でのライブラリ管理よりは(自分の中で)ずっと快適なのですが、
まだ不満はあります。

その一つ、特に囁かれる問題が、遅いという点です。

現在のcomposer の動作をソースコードの確認や -vvv オプションの付加により
なぜ遅いのかを考えてみます。
update 時に -vvv をつけると、より詳細なログが
標準出力に出てくるので、デバッグなどに便利です。

そうすると、見た感じから、以下がストレスを作る原因と考えられます。

遅い1) Package情報の入手

標準では、packagist.org からパッケージを入手する仕組みになって
いますが、この動作は現在2つに分類されます。
1つは、 /packages.json の入手です。このファイルには、
どのように参照すれば実際の依存情報を記したファイルが手に入るのか
という情報を記しています。
このダウンロードは毎回行われますが、さほど時間はかかりません。

問題は次です。上で入手した情報を元に依存情報の収集に向かうのですが、
これが、初回の場合大変時間がかかります。
(プロジェクトの規模によるかと思いますが、Symfony2 で動くプロジェクトであるpackagist の場合、
情報の取得だけで 17MB, 145個のファイルをせっせとダウンロードしていたのでした。)

2回目の場合は、cache から収集するため、 ずっと早くなります。
cache はデフォルトで 6ヶ月有効です。cache の場所は デフォルトでは
$HOME/.composer/cache/ なので、覗いてみるといいかもです。

遅い2) ソースコードの入手

これは、パッケージの定義によりけりです。
通常、安定したバージョンであれば、Github のアーカイブ (zip) から
入手されます。こちらも同様にキャッシュされます。
ただし、開発ライブラリなどであれば、gitレポジトリから clone
する場合が多いため、こちらがなかなか時間がかかります。
(こちらはアーカイブの場合キャッシュされます。
そのため、2回目は早くなります。)

これを踏まえた上で、解決案を考えてみた。

解決案) packagist.org JP Mirror or Proxy を作る

Tokyo から packagist.org まで 300ms – 500ms ほどの
レイテンシが存在するのです。
このサーバは、France にあるようです。ちょっと遠いですね。。。
日本のどっかにサーバを置くことで早くなるんじゃないかという説。

packagist に Nexus (Maven Repository/Proxy) みたいな Proxyの仕組みがあると嬉しいのですが。
* 参考記事: リポジトリ管理ツール「Nexus」でMavenをさらに活用しよう!
そこら辺は、改造のやりがいがあるかもしれないです。

【追記】
なお、社内ライブラリやプロジェクトの配布については
composer/satis を使うとよさそうです。
このツールは、Composer Repository のビルドツールです。

ちゃんと設定すると、packagist.org 上の依存ライブラリのアーカイブを
自分のサーバで配布することができます。

自身のプロジェクトで、自分で用意した Repository を使い、
packagist を無効化すると、かなり高速化されます。

あとで、これについての記事を書こうとおもいます。

続きまして、phpmatsuri2012 のフィードバックでございます。
おまたせいたしました。


* 相棒も一緒についてきました。

3回目の登場

なんだかんだ言って、3回目の登場です。
そして、おおーーー。ことし参加費安いじゃねーか。といってついうっかり「個人スポンサー」になってしまいました。
いや。しかしそれくらい払ってもいいイベントだと思っています。来るゲストはいつもながら豪華だったし、
内容もPHPだけに限らず、本当に幅広いことをやれるイベントだし。

そして、何より phpmatsuri の良さは開催場所の変化なのではないかなと思うわけです。
1回目の東京、そして2回目の大阪では、東京のリピーターと関西の人たちの mix-in が発生するわけです。
そして、3回目は、東京のリピーター・大阪のリピーター、あと九州の人たちの mix-in が起きました。
そして、来週は北海道との噂が囁かれているので、もっと mix-in がおきて、また新しい雰囲気になるのでは
とウキウキするわけであります。
@yando さん曰く、東京に戻った時が怖いかもということですがw

郡山△

郡山△ には合う度に郡山レジェンドを聞いている気がする。
この会も、そんな郡山さんの伝説が聞けるイベントの一つなのです。

“Dis Is It” という過去に行われた PHP Apocalypse というイベントの
キーノートを、さらにパワーアップしてビデオが追加されていました。
おそらく、このビデオはライブでないと見ることができなかったでしょう。
(本人曰く、これにパワーを注いだとかw)
私は、PHP Apocalypse に参加できなかったので、ライブで再び聞くことができてよかったです。


・十分に機能するか
・レイヤー可能か
進歩には漸進的な発展が必要

というのは、PHPという言語に限らず、もっと考えていきたい事ですな。。
郡山さんは、PHPという制約を正しく理解して、最高のものを作っていこうという感じにあふれている印象を
受けました。

闇イベント – レガシー戦隊登場

さて、phpmatsuri に突如去年から始まった夜中のプレゼン大会である
闇イベントが、今年もやって来ました。
今年の闇は、テーマが決まっていて「アン・リーダブルコード選手権」
というものでした。恐ろしい響きだ。

アン・リーダブルの恐ろしさを伝えるべく、結成された「レガシー戦隊レガシーズ」
http://www.flickr.com/photos/sanojimaru/8152331124/

レガシーブルーの人に詳しくお話を聞いたのですが、スライドは出さない
とのことでした。残念ですね!

複数人での開発になった途端、アン・リーダブルコードは生み出されるのでしょう。
脳みそが別物なのですから。早く脳みそのつながるマシーンとかできないかな

とか言ってました。
このようなイベントは貴重です。皆苦労しているのが、すごい伝わりました。

ファミコンゲームのUI研究してるだけなんだからね!!

作業が思ったより進んだのと、開発するパワーがなくなってきたので
夜中はファコミンで遊んでいました。@cakephper さんが持ってきたという
ファコミンソフトだったのですが、どれも中々キワモノが集まっておりました。
ファミコン世代まっただ中というわけではないので、ワリと新鮮です。

中でも、北斗の拳の操作方法がひどかった。
扉の移動方法が A+B+↑。ググってやっと判明wwwww

で、ファミコンをAM1時から4時くらいまでやってました。

今回の成果・大LT大会

phpmatsuri の醍醐味は、最後の大LT大会です。
なんと、今年は50人以上が LT しました。参加者の半分以上なのではないでしょうか。
毎回驚きます。

↓ ちなみに、私はこんな内容でやりました。

1. php-nabeの改良等

php-nabe は phpbrew や phpenv + phpbuild に不満を持ったため、個人的に作っている
phpのビルド、バージョン切替補助用のツールです。
phpのビルド部分は、bash script で書かているため、phpbrew のように php binary 自体を
必要としないこと、また extension のビルド・設定や、composer のインストールなども
補助するということを目標としています。 (最終的には composer.json に書かれた
ext-* を自動導入するような仕組みを作りたい)

今回は、ヘルプ機能をちゃんと動くようにしたり、 php-nabe use の挙動を、
phpunit などのインストールにも耐えられるようにしてみたり、
apt-get などで導入した、php を動かすために php-nabe disable コマンドを
用意してみたりしました。

個人的に作っているだけですが、フィードバックがありましたらぜひお声がけください。
https://github.com/kawahara/php-nabe

2. composer のドキュメント翻訳

Dustin のセッションの中でもありましたが、
composer は、広まるべきツールだと思いますが、日本語ドキュメントはありません。
というわけで、翻訳しています。
今回は、4章をやりました。4章を完成させ、5,6章を完成させればドメインを取るか
getcomposer.org に、日本語版ドキュメントを載せてもらえるよう交渉してみるなどを、
してみようと思います。

翻訳は、こちらです。
https://github.com/kawahara/composer/tree/japanese-doc-progress/jpdoc
手伝ってくれても、いいんじゃぞ!!

composer に関しては、git と一緒に、 XAMPP みたいなツールに乗れば
もっと広まるかなーと感じています。(とはいえ、どこに相談を投げればいいのかわからん
と感じました。)

3. Interactive Keynote の開発

日本の、keynote はインタラクティブ性にかける。ということで、平沢進の
インタラクティブライブに習い、Keynote にストーリー性をもたらすというものを
作っていました。 node.js で作っていますが、 phpjs を導入しているので
phpmatsuri でも問題無いです。

スライドに分岐が出てきたら、聞き手が どちらにするかというのをボタンを
押して決定するというシステムです。ソースコードも公開予定です。

最終的には、「異議あり!」ボタンとか「待った!」というボタンを
クライアント側に実装して、プレゼンの途中でもどんどん疑問をぶつけられる
雰囲気にしたいのですが、カプコンさん素材をクリエイティブ・コモンズにしてくれませんか?

また、「また、Fusic か…。」で、おなじみの、Fusic (phpmatsuriスポンサー) が
「それなんて、 ZENPRE 」という突っ込みをしていました。チャットや顔画面もあっていいですね!

まとめ

というわけで、私の、勝手に取得した秋休みは終わったわけです。
また仕事に戻ることを考えると、夏休みが終わってしまう小学生のような気分です。
今、福岡空港なのですが、間違えて沖縄便に乗りたいです。

投資家なしで、自由な発想でなにかを出していくっていうのは大事だと思うんですよ。
お金も大事だけど、そんなことより人間を幸せにするためにテクノロジーを真剣に考え、笑い合う。
そんなイベントだったと思います。