AspectPHPを構想する
AspectJとAspect指向を知った。そして、考えを改めた
AspectJ - Wikipediaという言語がある。
そしてアスペクト指向プログラミングというものがある。
この方法では絶対に、コードが書いてある通りに実行されているように見えなくて混乱を招くと思う。だからあんまり多用するのは控えて、使うとしてもドキュメントをちゃんと残して・・・ってことになるとずっと思っていた。
改心
例えば、Logを残したい。いくつも対象となるクラスがあって、その特定のメソッドが例外を発生されて、プログラムを終了させようとしているときに
Logを残したいって要望があったとする。通常考えられる方法はその対象メソッドをtry-catchで囲んで、Loggerクラスのメソッドをコールしてログが落ちるようにする。
でもこの場合の修正コード量が多いことや、それぞれのクラスに純粋には必要のないコードが増えていることが問題点としてあげられると思う。
そのときはAspect指向を使って、メソッドの例外発生時に呼ばれるコールバック関数を指定してやると解決できる。
おぉすばらしい。コード量も減るし、クラスの機能が純粋に絞られていく〜
AspectPHPを実装する
Javascriptなら関数の扱いが簡単で、定義済みの関数を編集することもできる。加えて、nativeでなければ関数の実装コードを参照することもできるので、結構簡単にできそうな気がしている。
でもJavascriptでは使いたい場面がまだないので実装はパスする。
PHPで下のようなコードがあって
function hoge(){ echo 'hoge'; // <- ここでログを出力したい } function hoge(){ echo 'hoge'; L:debug('ログ'); // <-これだとhogeに必要な機能以外が実装されている }
下のようなfunction hogeにしたくなかったのでAspect指向なPHPを実装し始めてみた。
最終的に上のコードが
function hoge(){
echo 'hoge';
}
$aspect = AspectFunction( 'hoge' );
$aspect->addPointCut( 'after', ' L:debug('ログ');' );
無名関数はマジでハマる
ここに書いている通り、create_functionの作る関数の関数名は先頭にNULLが入っている。
なので、無名関数の中で前に作った無名関数を作ろうとすると都合が悪い。
$funcName = create_function('', 'echo "test";'); create_function('', $funcName.'();' );
とかすると、二つ目のcreate_functionがこける。たぶん、$funcNameが文字列になってしまったら、NULL文字があるのでそこで文字列終了と判定されて、正しく解釈されないのだと思う。
なので、ユニークな名前を作りながら指定されたコールバック関数を作っていくことにした。
今の開発環境がWindows版でPHP5.25でrunkitの関数が正しく動作しなくて、クラスに関する関数だけしか使えないようだ。
関数の振る舞いを変えられるようにならないと、目標が最後までいきそうにない。