Document

アスペクト指向言語のための
独立性の高いパッケージシステム
今吉竜之介 柳澤佳里 千葉滋
東京工業大学
アスペクト指向言語(AOP)

横断的関心事を分離して記述可能
:
move();
update();
:
:
move();
update();
:
:
move();
update();
:
オブジェクト指向の場合
アスペクト指向の場合
aspect UpdateAspect {
pointcut pc() :
call(void Point.move());
moveの直後に
updateを呼び出す
class Point {
move() { ... }
}
after() : pc() { update(); }
}

updateを呼び出す
コードが複数個所に
散在
アスペクト指向では、
updateを呼び出すコードは
一箇所のみ

拡張、修正が容易
例:描画ソフトの共同開発

ソフト全体をモジュールとして分割し、
それぞれ異なる開発者が作成

開発者によってはアスペクトを最初から利用

モジュール内でのプログラムの見通しが向上

E.g.) observer pattern、トランザクション処理など
FigureModule
WindowModule
図形を管理するパッケージ
ウィンドウ本体を管理する
パッケージ
図形の状態変化を
通知するために AOP を使用
FigureModule

それぞれの図形は色を持ち、setColorで変更する
class Point {
void setColor(Color c) { ... }
}
class Circle {
void setColor(Color c) { ... }
}
class Panel {
void setColor(Color c) { ... }
}
FigureModuleの Screen
との結合テストは上手くい
く
aspect UpdateScreen {
pointcut pc() :
execution(void *.setColor(..));
after() : pc() {
Screen.update();
}
}
色の変更時を指定
色の変更直後に
再描画
WindowModule

Frameクラスを実装

フレームの色を変更する
メソッド名がsetColor
フレーム色の
変更直後に再描画
class Frame {
void setColor(Color c) {
/* フレーム色を変更 */
Screen.update();
}
}
WindowModuleの
Screenとの結合テストは
上手くいく
コンポーネント毎の開発が終わったので、次はそれらを結合
結合時に不具合

フレームの色を変更すると画面がちらつく!
class Point {
void setColor(Color c) { ... }
}
aspect UpdateScreen {
pointcut pc() :
execution(void *.setColor(..));
}
名前の予期せぬ一致
クラス側のupdate直後に
アスペクト側で再びupdateを
実行してしまう
class Frame {
void setColor(Color c) {
/* フレーム色の変更 */
Screen.update();
}
}
fragile pointcut問題

アスペクトがプログラムに予期しない影響を与える
aspect
class
fragile pointcut
 ポイントカットで指定した条件と
class
名前が偶然一致すると発現
ポイントカット指定でワイルドカードを
使用すると危険
AspectJのセマンティクスの修正を
提案

アドバイスの織り込み範囲を変更



同一のパッケージのみにアドバイスを織り込む
パッケージ外のジョインポイントは選択不可
現状のAspectJの動作では間違いやすい

fragile pointcut 問題
class
aspect
×
class
修正の効果:
モジュールの独立性が向上

パッケージ単位で再利用性が向上

再利用の前後でプログラムの挙動が変化しない


プログラムとアスペクトが切り離されない
各パッケージの挙動が予測しやすい

プログラムがシステムの別の部分にあるアスペクトの影響を
受けない

ワイルドカードによる誤った選択を防ぐ


名前の条件が一致しても、無関係なモジュールには無影響
無関係なクラスにあるメソッド名などを気にせずに開発可能
修正による弊害:
パッケージをまたがるアスペクト

重複するアスペクトが必要になる場合が存在
例: ロギング用のアスペクト
aspect LoggerAspect {
pointcut pc() :
call(void Point.move());
before() : pc() {
/* ログの取得 */
}
}
パッケージの数だけ重複
:
move();
:
:
move();
:
:
move();
:
class Point {
move() { ... }
}
修正案へ追加:
織り込みについての拡張ルール


インターフェイスに対するアドバイス
公開ポイントカット



パッケージをまたがるアスペクトへの対応
アスペクトを用いた observer pattern などにも対応
明示的な記述により、パッケージをまたがる
アスペクトを可能に

予期せぬ織り込みを引き起こさないよう留意して設計
インターフェイスに対するアドバイス

特定のクラスメンバへのパッケージ外からの
アクセス全てに作用するアドバイス
:
move();
:
:
move();
:
:
move();
:
アスペクトを一箇所に記述可能
aspect
例) 外部からのアクセスの前に
必ずassertionを実行
class Point {
move() { ... }
}
パッケージ内のクラスメンバへの
call,set,getに
[&& !within(自パッケージ名)]
を追加で記述すると反映
ロギング用のアスペクトを可能に
:
move();
:
:
move();
:
:
move();
:
aspect LoggerAspect {
pointcut pc() :
call(void Point. move())
&& !within(FigureComponent);
before() : pc() { /*ログの取得*/ }
}
public class Point {
public void move() { ... }
}
この拡張によって重複するアスペクトを回避
予期せぬ織り込みの回避

明示的に記述される必要があるため、予期せぬ
織り込みにはならない

[&& !within(自パッケージ名)]を付加しない限り、
この拡張ルールは反映されない

選択されるジョインポイントはパッケージ外


パッケージ内メソッドの呼び出し元
予期せぬメソッド呼び出しが選択され、アドバイスが織
り込まれる可能性は少ない
修正によるもうひとつの弊害:
observerクラスとアスペクトの隔絶
aspect UndoAspect {
pointcut pc() :
execution(void *.move());
before() : pc() {
//undo のための履歴保存
}
}
しかしアスペクトをUndo側の
パッケージに置いても問題は
解決されない
class Point {
move() {...}
}
Undo
Undoは別のモジュールの処理なので、
UndoAspectもUndo側に置きたい
class Point {
move() { ... }
}
×
別パッケージのイベントは選択できない
Undo
公開ポイントカット

抽象アスペクトが定義したポイントカットは
公開ポイントカットとなる

公開ポイントカットは子アスペクトのみ使用可能

子は親と同一のパッケージに属していると見なされる
抽象
aspect
aspect
class
abstract aspect Parent {
pointcut pc() : ...
}
class
aspect Child extends Parent {
before() : pc() {...}
}
observerクラスとアスペクトを同一
パッケージに記述可能に
public abstract aspect UpdateAspect {
pointcut pc() :
execution(void *.move());
}
aspect UndoAspect
extends UpdateAspect {
before() : pc() {
// Undoのための履歴保存
}
}
public class Point {
public void move() { ... }
}
public class Undo {
void set() { ... }
}
この拡張によって、パッケージ外からイベントを選択可能
公開ポイントカットの利点と妥当性

利点

プログラムのイベントをパッケージ外部からも選択可能


フレームワークの設計に利用可能



例) アスペクト指向を用いた observer pattern の実装など
親アスペクトで拡張ポイントを示し、子アスペクトでそのポイントを
利用者が自由に拡張する
情報隠蔽の仕組みを提供
妥当性

公開側と継承側の両方に明示的な宣言が必要なため、
予期せぬ織り込みにはならない
システムの実装

AspectJ言語を拡張してセマンティクスを
変更

abc(AspectBench Compiler)を
改造して実装

全てのジョインポイントは、そこに
織り込まれるアドバイスのリストを保持




織り込む直前に、そのリストにある全ての
アスペクトの情報をチェック
織り込み制限のルールに適していなければ、
そのアドバイスはリストから除外
全てのジョインポイントに対して同様に処理
インタータイプ宣言にも同様の処理
Aspect Info
Advice Weaving
を拡張
実験:AJHotDrawの修正

セマンティクスの変更により、アスペクトのソースコードが
どのように変化するかを計測

重複するアスペクトの有無
記述不可能なアスペクトの有無

対象: AJHotDraw (ver 0.3)




アスペクト指向で設計されたDrawing Tool
コード数:41903行 / ファイル数:300個
本システム下でも正しく動作するようにアスペクトを修正


織り込み条件の変更により、オリジナルのプログラムと挙動が異なるため
クラス側のソースコードは変更も移動も無し
実験結果
・アスペクトを含むパッケージ数
・アスペクトのファイル数
・ソースコード上のアドバイスの数
・インタータイプ宣言の数
・織り込まれたアドバイスの数


修正前
修正後
3
10
5
31
44
7
17
5
31
44
単一アスペクトが複数
ファイル、パッケージに
分割された
コードの重複は無し
アスペクトのファイル数、パッケージ数が増加するが、
重複するアスペクトは無い
AJHotDrawで記述不可能なアスペクトは無い

拡張ルールはAJHotDrawで使用されなかった

observer pattern を実装するアスペクトは存在したが、
パッケージをまたいでいなかった
関連研究:AspectJの場合


AspectJではwithinを用いることで
織り込みを制限
 修正後のセマンティクスも、
ある程度までなら再現可能
aspect UpdateDisplay {
pointcut pc() :
execution(void *.setColor(..))
&& within(FigureComponent.*);
pointcut pc2() :
execution(void *.move(..))
&& within(FigureComponent.*);
全てのポイントカットへの記述は
手間がかかる
}

記述を忘れたり、間違った条件を
付けたりした場合にチェックする
機構が存在しない
 本システムでは、暗黙のうちに
正しい条件文が付加される
関連研究:
Open Module [Aldrich et al. ’06]

[module]という単位でクラスをまとめ、
外部のアスペクトからのアクセスを制御
module FigureModule {
 公開したいジョインポイントを
class Point || Circle || Panel;
任意に記述
friend DebuggingAspect;
expose call(void Point.setColor(..);

}
ジョインポイントが一致すると
無関係でも選択される恐れ
 本研究は名前付ポイントカットを
公開するため、予期しない選択は排除

アスペクトを含むようなパッケージの
再利用については考慮していない
関連研究:ccJava [境ら ’06]

アスペクトの織り込みに対応し
た「織り込みインターフェイス」
を導入



公開した部分のみ織り込み
アドバイスもモジュールとして独立 w_interface xDraw {
パッケージ再利用に不向き

w_interface xFig {
pointcut set() :
execution(void setColor(..));
import after set();
}
修正の際に、織り込みインター
フェイスの分だけ手間が増加
pointcut draw() :
execution(void update());
export draw();
}
weave {
class Point implements xFig;
class Display implements xDraw;
connect(xDraw.draw, xFig.set);
}
まとめ

AspectJのセマンティクスの修正を提案




アスペクトは同一パッケージ内のジョインポイントのみ選択可能
 パッケージの独立性の向上
拡張ルール
 アスペクトの記述力を保つためのルール
 パッケージの独立性を壊さないように留意
abcを改造して実装
AJHotDrawで実験


修正セマンティクス下で記述不能なアスペクトは無い
拡張ルールの使用は無い
今後の課題

セマンティクスの修正を適用した際の副作用の
検証


アドバイスやポイントカットの総数が
増加する可能性がある
拡張ルールの洗練


拡張ルールの適用例を発見
拡張ルールの追加、修正


クラスがパッケージをまたいで継承している場合を考察
内部クラスへの対応を考察 など