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が見られるので便利です。一度お試し下さい。

Perlクックブック〈VOLUME1〉