アスペクト指向言語のための
独立性の高いパッケージシステム
今吉竜之介 柳澤佳里 千葉滋
東京工業大学
アスペクト指向言語(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で実験
修正セマンティクス下で記述不能なアスペクトは無い
拡張ルールの使用は無い
今後の課題
セマンティクスの修正を適用した際の副作用の
検証
アドバイスやポイントカットの総数が
増加する可能性がある
拡張ルールの洗練
拡張ルールの適用例を発見
拡張ルールの追加、修正
クラスがパッケージをまたいで継承している場合を考察
内部クラスへの対応を考察 など
© Copyright 2026 ExpyDoc