PHP::Sessionのコードを読む: t/lib/TestUtil.pm
経緯
数週間前、SixApartの宮川さんが書かれたCPANモジュールを一度読んでみたい!と思いました。それで宮川さんの連載記事「PerlStyle」の「Test! Test! Test!」でPHP::Sessionが取り上げられていたので、無謀にもそのコードを読んでみることにしました。
ネットで検索するとすぐに見つかりました。ここですね。
まだCPANモジュールの作り方の知識は全然ないので、PHP::Sessionの中でとにかく理解できそうなコードを探しました。そこで今のレベルでも読めそうだと思ったのは、テストディレクトリのlib(t/lib)以下にあった「TestUtil.pm」でした。単にファイルを読み書きする何の変哲もないモジュールだと直感的に理解しました。どう見ても重要なモジュールではないことは、すぐにわかりましたが、それでも読んでみる価値はあると思いました。
The code
そのコードは以下のようなコードです。23行という短い何の変哲もなさそうなコードです。でも読む価値はあります。
# vi /root/.cpan/build/PHP-Session-0.25/t/lib/TestUtil.pm package TestUtil; require Exporter; @ISA = qw(Exporter); @EXPORT = qw(write_file read_file); use strict; use FileHandle; sub write_file { my($file, $cont) = @_; my $out = FileHandle->new("> $file") or die "$file: $!"; $out->print($cont); } sub read_file { my $file = shift; my $in = FileHandle->new($file) or die "$file: $!"; local $/; my $cont = <$in>; return $cont; } 1;
得られたノウハウ
このコードを読んで、理解したことを以下に挙げます。
- モジュール名は「*.pm」で
- パッケージ宣言は「package foo」で(fooはファイル名から「.pm」を除いたもの)
- Exporterモジュールを@ISAを使って継承
- write_fileとread_fileをモジュール外から利用できるようにインタフェースをエクスポート(公開)
- FileHandleモジュールでオブジェクト指向的にファイルを操作(open演算子は使わない)
- read_fileにある「local $/;」がポイント(今日、謎が解けました)
- モジュールの最後は「1;」を忘れずに
このたった23行のモジュールからも、宮川さんのノウハウをこんなにも得ることができました。Javaを使ったことがあるので、パッケージやエクスポートの概念を扱っていることはすぐに想像がつきました。
「local $/;」の謎
「local $/;」の謎が、今日やっと解けました。今日は研究室に用事があったので、そのついでに大学の図書館に行きました。前から気になっていた「Perlクックブック VOLUME 1」を図書館で読んでいると、ふと思いました。「$/」が載っていないかなぁと。そして、索引を調べたら、捜し求めていた答えが載っていたのでした。
$/を未定義にすると、1度の読み込みで1つのファイル全体が取り込まれます。
レシピ7.14 Unixスタイルのフィルタプログラムを書く より
また参考になるコードも載っていました。以下に引用します。
{ # local用ブロック local $/; # レコードセパレータを未定義にする while (<>) { # 処理を書く: # 呼び出された関数は未定義の$/を参照する } } # ここで元の値が戻される
こういうことだったのですね。謎が1つ解けて、一安心です。
さいごに
普通なら誰も読もうと思わないモジュールにも思いがけないノウハウが詰っていましたね。また宮川さんの興味深いコードを解読できたら、紹介したいと思います。PHP::Sessionのコアのコードが読めるようにもっと勉強します。(笑
おまけ
宮川さんも、ミス?をされるのですね。証拠をお見せしましょう。PHP-Session-0.01では「or die」を書くのを忘れられています。どのバージョンでこのミスを修正されたのかはちょっと把握していません。
http://search.cpan.org/diff?from=PHP-Session-0.01&to=PHP-Session-0.25#t/lib/TestUtil.pm
CPANのサイトでdiffが見られるので便利です。一度お試し下さい。