28
PECL-AOP ののの @Hiraku

pecl-AOPの紹介

Embed Size (px)

DESCRIPTION

PHP勉強会で発表した内容です

Citation preview

Page 1: pecl-AOPの紹介

PECL-AOPの紹介

@Hiraku

Page 2: pecl-AOPの紹介

自己紹介 @Hiraku( 中野 拓 ) Web プログラマやってます PHP 歴 4 年

http://blog.tojiru.net/ https://github.com/hirak

Page 3: pecl-AOPの紹介

AOP のてきとーな解説

Page 4: pecl-AOPの紹介

Wikipedia 先生の解説

アスペクト指向プログラミング Aspect Oriented Programming

オブジェクト指向ではうまく分離できない特徴(クラス間を横断 (cross-cutting) するような機能)を「アスペクト」とみなし、アスペクト記述言語をもちいて分離して記述することでプログラムに柔軟性をもたせようとする試み。

Page 5: pecl-AOPの紹介

具体例 例外処理 関数キャッシュ ロギング トランザクション 実行時間の計測

etc..

Page 6: pecl-AOPの紹介

例外処理

try { doSomething(); //…

} catch (OutOfBoundsException $e) { recoverError($e);

} catch (RangeException $e) { recoverError($e);

}

Page 7: pecl-AOPの紹介

class A { function a() { try { doSomething(); //… } catch (RuntimeException $e) { processError($e); } } function b() { try { doSomething(); //… } catch (RuntimeException $e) { processError($e); } } function c() { try { doSomething(); //… } catch (RuntimeException $e) { processError($e); } }}

よくある光景

Page 8: pecl-AOPの紹介

例外処理の問題 いくらエラーの回復処理を関数化して

も、 try ~ catch ブロック自体は何度も書くことに

DRY(Don't Repeat Yourself) じゃない 「これ、さっきも書いたコードだな

…」

Page 9: pecl-AOPの紹介

クラス分割や関数分割だけだとうまくモジュール化できないもの

横断的関心事= Aspect

Page 10: pecl-AOPの紹介

こういうパターンが多い function a() { try { doSomething(); //… } catch (RuntimeException $e) { processError($e); } }

try { //…} catch (RuntimeException $e) { processError($e);}

function a() { doSomething(); //…}

こう分割できたらいいのに…

Page 11: pecl-AOPの紹介

pecl-AOP の概要

Page 12: pecl-AOPの紹介

pecl-AOP

AOP を extension によって実装したもの

http://pecl.php.net/package/AOP

インストールさえできれば文法はわかりやすい

runkit っぽい

# pecl install aop-beta

Page 13: pecl-AOPの紹介

AOP 用語 (pecl-AOP の場合 ) Advice

Aspect をモジュール化したもの。 pecl-AOP ではコールバック関数で実装

JoinpointAdvice を織り込める場所。

weaveAdvice を Joinpoint に差し込むこと。

Page 14: pecl-AOPの紹介

例外処理を Advice 化function processError(AopJoinpoint $joinpoint) { try { return $joinpoint->process();

} catch (RuntimeException $e) { // エラー処理

}}

Page 15: pecl-AOPの紹介

Weave( 織り込む )aop_add_around('A->*()', 'processError');

A クラスのすべてのメソッドに processError() を織り込む、という指令

これで A クラスのすべてのメソッドは、 processError 経由で呼ばれるようになる

Page 16: pecl-AOPの紹介

class A { function a() { try { doSomething(); //… } catch (RuntimeException $e) { processError($e); } } function b() { try { doSomething(); //… } catch (RuntimeException $e) { processError($e); } } function c() { try { doSomething(); //… } catch (RuntimeException $e) { processError($e); } }}

Page 17: pecl-AOPの紹介

class A { function a() { doSomething(); //… } function b() { doSomething(); //… } function c() { doSomething(); //… }}

aop_add_around('A->*()', function (AopJoinpoint $joinpoint) { try { return $joinpoint->process(); } catch (RuntimeException $e) { // エラー処理 }});

DRY になったね!

Page 18: pecl-AOPの紹介

対応 Joinpoint

before any method / function call after any method / function call around any method / function call During the arousing of an exception

of any method / function after any method / function call,

should the method terminate normally or not (triggers an exception or not)

Page 19: pecl-AOPの紹介

応用例はいっぱいありそう 例外処理 関数キャッシュ 入出力のフィルタリング ロギング トランザクション 実行時間の計測

etc..

Page 20: pecl-AOPの紹介

関数キャッシュ 関数自体にキャッシュシステムを組み込む

add_aop_around('A->*()', function (AopJoinpoint $joinpoint) { $key = $joinpoint->getClassName() . '->' . $joinpoint->getMethodName(); $cache = apc_fetch($key, $success);

if ($success) { return $cache; }

$result = $joinpoint->process(); apc_store($key, $result);

return $result;});

Page 21: pecl-AOPの紹介

もっと応用(pecl-AOP に限った話 )

Page 22: pecl-AOPの紹介

pecl-AOP のヤバいところ 既存の関数やメソッドなら何でも置き

換え可能

テストのモックとして強力

Page 23: pecl-AOPの紹介

rand() の固定化

rand() を同じ値しか返さない関数で置換 何度実行しても 0 を返す

aop_add_around('rand()', function () { return 0;});

var_dump(rand());var_dump(rand());var_dump(rand());

Page 24: pecl-AOPの紹介

time() の固定化

time() も初期値を自由に変更できる

201X 年を再現する、ということが可能timecop の方が特化してて便利だけど…

それに近いことが可能https://github.com/hnw/php-timecop

aop_add_around('time()', function () { return 0;});

var_dump(time());

Page 25: pecl-AOPの紹介

何でも置き換え WebAPI にリクエストする部分を固定

化とか DB に接続する部分を固定化とか

要はクラスの継承と無関係な継承・上書きが可能

自由すぎてわけわからん

超強力 & 凶悪

Page 26: pecl-AOPの紹介

まとめ

Page 27: pecl-AOPの紹介

pecl-AOP 面白いよ 超強力 & 凶悪

テストのお供に 書きにくいコードをすっきり DRY に

PHP のゆるさが5割増しになるのが悩ましい

Page 28: pecl-AOPの紹介

注意点 まだ beta 扱いです。 インストールもこけたりテストもこけ

たりする segmentation fault もよく起きる

実戦投入はまだ危険