170 likes | 266 Views
複数個の Joinpoint の集合を 対象とした Pointcut を 記述可能なアスペクト指向言語. 理学部 情報科学科 指導教官 千葉 滋 助教授 学籍番号 01_14577 竹内 秀行. 人材管理モジュール. 給与台帳モジュール. 社員. 社員. 調査部. 販売部. 平社員. 管理職. 調査担当. 販売担当. 調査担当. 調査担当部長. 調査担当部長. 販売担当部長. 販売担当. 販売担当部長. 異なるクラス階層を持つ変更. 既存のソフトウェアに新しい役割を持たせる オブジェクト指向で設計すると階層構造が破綻
E N D
複数個のJoinpointの集合を対象としたPointcutを記述可能なアスペクト指向言語 理学部 情報科学科 指導教官 千葉 滋 助教授 学籍番号 01_14577 竹内 秀行
人材管理モジュール 給与台帳モジュール 社員 社員 調査部 販売部 平社員 管理職 調査担当 販売担当 調査担当 調査担当部長 調査担当部長 販売担当部長 販売担当 販売担当部長 異なるクラス階層を持つ変更 • 既存のソフトウェアに新しい役割を持たせる • オブジェクト指向で設計すると階層構造が破綻 • 別々に記述できたほうが開発しやすい
社員管理::販売担当 表示() 表示() 給料() 部下() 名前() 名前() 人材管理::販売担当 給与台帳::販売担当 名前() 表示() 給料() 表示() 名前() 部下() クラスの合成 • 同じ対象を表現するクラス同士を合成する • それぞれのクラスが持つすべてのメソッドおよびフィールドを一つのクラスから利用できるように • メソッド名が衝突した場合のルールは別に記述
既存のアスペクト指向言語 • AspectJ[Kiczalesら’01] • 現在最も一般的なアスペクト指向言語 • 特徴点 (joinpoint) を探し出しコードを挿入 • メソッド呼び出しやフィールドアクセス等 • Pointcut • Joinpointを抽出するための記述 • Advice • Joinpointの新しい振る舞いをJavaコードで定義 call(void System.out.println(..)) && within(Logger) before() : log() { System.out.println(“[” + now() + “] ”); }
AspectJによるクラス階層の合成 • AspectJでの方針 • クラス階層を別々に開発 • インスタンス化時に関連付け • メソッド呼び出し等をpointcut • AspectJの問題点 • pointcut で単一の joinpoint しか抽出できない • リフレクションを利用しなければならない • 一方向にしか関連付けることができない
単一のJoinpointの制限① 人材管理 給与台帳 販売担当 調査担当 Aspect 販売担当 調査担当 Aspect インスタンス化時にClass.forName()で探してバインド • インスタンス化を pointcut し、リフレクションで関連付け • 実行速度の低下
単一のJoinpointの制限② 人材管理::販売担当 給与台帳::販売担当 名前() Aspect 表示() 給料() 表示() 名前() 部下() • 一方向にしか関連付けることができない • 基となるモジュールをあらかじめ決める必要がある • 逆方向の参照はオブジェクト同士のマッピングが必要
提案:複数個のJoinpointの集合を 選択できるPointcutの記述 • pointcut に連結演算子(##)を導入 • pointcut式 ## pointcut式 • 左右の式で得られるjoinpoint集合の配列を連結 • 従来の pointcut式の結果 は要素1の配列として扱う • 利用例 • 人材管理パッケージのクラスと給与台帳パッケージのクラスを抽出 • Jugglingクラスのstart()とend()の呼び出しを抽出 class(personnel.*) ## class(payroll.*) call(Juggling.start ()) ## call(Juggling.end ())
クラス階層の合成 • composition advice の導入 • 複数のクラスを Joinpoint としてとる • Hyper/J[Ossherら’00]の記述を応用 composition() : class(personnel.*) ## class(payroll.*) { mergeByName; override String $2.name() with String $1.name(); String $composed.toString() { StringBuffer ret = new StringBuffer(); for (int i = 0; i < $result.length; ++i) ret.append($result[i]); return ret.toString(); } }
Composition Advice • mergeByName; • 何も指定されなければ同じ名前のメソッドを結合 • 結合後のメソッドは合成前のクラスのメソッドを順番に呼び出し最後の呼び出しの結果を返り値とする • override String $2.name() with String $1.name(); • name()メソッドは結合せずに二番目のjoinpointのメソッドを呼び出す • $1,$2はpointcutによって得られたjoinpoint配列の要素 • String $composed.toString() { … } • 結合されたtoString()の返り値を再構成する
実装 • 拡張可能なコンパイラ • pointcut および advice を Java で追加可能 • Polyglot, Javassistを用いて作成 • コンパイル速度の比較 • PureTLS Toolkits のコンパイルおよび合成 • クラス数: 127個 行数: 約18000行 • joinpoint: 6384個 うち合成対象箇所: のべ1052個 *内部エラーにより終了(バイトコード変換で問題発生)
関連研究 • Hyper/J • 異なるモジュールの合成を行うアスペクト指向システム • メソッド、フィールド、クラスを既存のモジュールから切り出し他のモジュールに合成を行う • 自由度が高い反面、ユーザーが面倒を見なければならないところが多い
まとめ • 複数個のJoinpointの集合 • pointcut式に連結演算子を導入 • composition adviceによるクラス階層の合成 • 今後の課題 • pointcut による記述の柔軟性を生かし切れていない • advice での joinpointの扱いの整合性がとれていない • 他の複数の joinpoint を必要とするアスペクトの記述
おしまい 質問用スライドに続く…
単一のJoinpointの限界③ 人材管理::販売担当 給与台帳::販売担当 役職() 解雇() Aspect 性別() 名前() 表示() 解雇() 備考() 表示() 役職() 名前() 性別() 備考() 一つ一つ記述する • メソッド・フィールドごとに一つのアドバイスが必要 • 保守が難しい
Hyper/Jによる解法 • 特徴点の抽出 • その振る舞いの定義 package personnel : Feature.Personnel package payroll : Feature.Payroll relationships: mergeByName; override operation Feature.Payroll.name with operation Feature.Personnel.name; AspectJと何が違う? 特徴点 (Joinpoint) が二つある
AspectJ での実際のコード例 public aspect PersonnelWithPayroll perthis(this(personnel.Employee+)) { private payroll.Employee payroll; before(personnel.Employee personnel) : execution(personnel.Employee+.new()) && this(personnel) { String name = personnel.getClass().getName(); name = nameのクラス名だけ取り出す; payroll = Class.forName( “payroll.” +name).newInstance(); } after(String name) : execution(void personnel.Employee+.setName(String)) && args(name) { payroll.setName(name); } … }