アスペクト指向言語のための 独立性の高いパッケージシステム 今吉竜之介 柳澤佳里 千葉滋 東京工業大学 アスペクト指向言語(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 2024 ExpyDoc