Study on Aspect Extraction
and Program Analysis
for Effective Software Development
石尾 隆
井上研究室 D3
[email protected]
ソフトウェア開発支援のためのアスペク
ト抽出とプログラム解析に関する研究
アスペクト指向プログラミング
Gregor Kiczales
らによって提案 (ECOOP 199
8)
目標: 「横断的関心事の分離」
Separation of Crosscutting Concerns
新しいモジュール単位「アスペクト」の提案
AspectJ
という Java の拡張実装も同時に提案
Java
に,アスペクトを記述するための言語要素を
追加
一部企業では,実際のソフトウェア開発でも使われ
ている
関心事とは
「ソフトウェアが持つべき機能,品質」
1つの関心事はできるだけ1つのモジュールにまとめる
(構造の把握) 各モジュールの役割が把握しやすい
(再利用) 同じ処理を再利用可能になる
(変更の局所化) 変更をモジュールの内部に閉じ込める
横断的関心事
達成するために,複数のモジュールにコードを書く必要がある
処理
例 : 「メソッドの呼び出しをファイルに記録する」
各メソッドの先頭などにログ記録処理を追加する必要あり
モジュール単位「アスペクト」の
役割
横断的関心事のモジュール化
アスペクト : 指定されたルールに基づいて
,処理の追加・置換などを行なう
Class Logger
logs()
メソッドが呼ばれるとき
メソッド呼び出しの前に logs を呼び出す
Logging
Aspect
Class Line
setColor
Class Circle
setRadius
アスペクト指向プログラミングの
利点
「いつ,何をするか」のルールによる記述
実行するタイミングが変更されやすい処理のモジュール
化に適する
例 : ログを取る対象が変わっても,アスペクトの変更だけで
済む
–
従来は,ログを取る処理すべてを検索してきて,変更する必要があっ
た
クラスの機能とは関係ない処理の呼び出しをクラ
スから除去する
クラス側は,主目的の機能だけを記述できる
保守性,再利用性の向上
アスペクトの用途
Development Aspect
ソフトウェア開発作業を支援するための処理
ロギング,パフォーマンス計測
Production Aspect
ソフトウェアの機能を実現するもの
ユーザ認証(アクセス管理),データベースの暗号
化など
Runtime Aspect
実行時の性能改善
メモリ節約,ファイル先読み
研究の動向
アスペクトの有効な使い方を探る
Runtime Aspect
の使い方が最初に提案された
開発者が手で最適化したコードと比較して,
半分以下のコード量で実用的なレベルの性能を達成
Production Aspect
が最も活発
実際に,ソフトウェアを開発したケーススタディが多
い
Development Aspect
はあまり注目されていない
ロギング,パフォーマンス計測程度
本研究の着眼点
Development Aspect
に属する関心事は頻繁に登場する
開発者はテスト用,デバッグ用などのコードをよく書く
アプリケーションドメインに依存せず発生する
通常,プログラムの複数の場所に,コードが分散する
Development Aspect
のモジュール化は,
開発作業を効率よく進めるために有効である
2つの横断的関心事について,アスペクトでの実現を
提案
プログラムの動的解析
オブジェクトを横断した表明
アスペクトの複雑さ
一方で,アスペクトの問題点も指摘されている
アスペクトのクラスへの依存性
Fragile Base-Code Problem
「いつ処理を実行するか」という条件にメソッド名やクラス名を
使う
クラス側で名前を変更すると,アスペクトも修正が必要
AspectJ
の場合,統合開発環境で対応
アスペクト間の干渉
Inter-aspect problem
「他のアスペクトに影響を与えるアスペクト」が問題を引き起こ
す
アスペクトの干渉
例 :
データベースコンポーネントに対して,
「メソッド呼び出しの引数を記録する」アスペ
クトと,
「データベースに渡す文字列引数を暗号化し,
戻り値の内容を復号化する」アスペクトを適用
する
記録される文字列は,暗号化されているべきか
?
Database
Logger
Logging
Encryption
A client
call
干渉の発見
アスペクトの干渉問題の難しさ
アスペクトの場合,必要ない限り,順序の指定をしない
実行順序の影響を受けるものは少ない
今までは,処理の実行順序を(とりあえず)指定する必要が
あった
プログラムスライシングの導入によるデバッグ支援
指定した変数に影響を与えうるプログラム文の集合を抽出
する
オブジェクト指向プログラミングに対応した手法を拡張
あるアスペクトのコードが,他のアスペクトからの影響を
受けているか調べることが可能
研究内容のまとめ
2つの Development Aspect の提案
プログラムの動的解析
オブジェクトを横断した表明
-
アプリケーションに依存せず発生する横断的関心事
-
モジュール性,保守性への影響を評価
プログラムスライシングによるデバッグ支援
既存のスライシング技術をアスペクト指向に拡張
アスペクト指向プログラミングの利用には重要
AspectJ
プログラムに適用した結果を評価
論文の構成
1章 : Introduction
2章 : Dynamic Analysis for Program Slicing using
Aspect-Oriented Technique
文献 [2, 7]
プログラムの動的解析処理をアスペクトとして実現
3章 : Modularization of Assertions Crosscutting Objects
文献 [3, 6]
表明の記述をアスペクトとして実現 .
4章 : Debugging Support for Aspect-Oriented Program
Based on Program Slicing and Call Graph
文献 [1, 5]
アスペクト指向プログラムに対するデバッグ支援
アスペクトの分類(再掲) : 用途で
の分類
Development Aspect
ソフトウェア開発作業を支援するための処理
ロギング,パフォーマンス計測
Production Aspect
ソフトウェアの機能を実現するもの
ユーザ認証(アクセス管理),データベースの暗号
化など
Runtime Aspect
実行時の性能改善
メモリ節約,ファイル先読み
アスペクトの分類 : 構造での分類
Homogeneous Aspect
多数の場所での同じ処理
システムの広範囲に渡るロギングなど
従来は,プログラム変換など,他の方法でも対応していた
Heterogeneous Aspect
クラスごとに異なる処理が,いくつかの場所に追加され
る
アクセス権管理など様々
ユーザ認証が必要な処理開始前に
割り込んで認証を要求
認証がないままデータベースへの
アクセスがないか監視
1つの目的のために
必要な処理が
複数ある
アスペクトの設計方法 (1/2)
一般的指針
同時に変更されやすいものを一箇所にまとめる
Role-based Design
との親和性
†
例 : Observer パターンのアスペクトとしての実現
Observer Role
と Subject Role との間の関連を定義
– Subject
が更新されたときは Observer に通知する
実際の「アクター」を Role に割り当てる
– Window
が Observer 役, File が Subject 役
Role
間の関連をアスペクトに落とし込む
役割を担当するアクターはクラスとして実現する
アスペクトの設計方法 (2/2)
アクション・グラフを使った分析
†
システムの動作(アクション)の関連を分析
複数のアクションに関連したアクションをアス
ペクトとする
授業履修システムの分析例 :
「学生が授業に登録するとき,その情報を記録する」
「学生が授業の登録を解除するとき,その情報を記録
する」
Elisa Baniassad and Siobhan Clarke: Theme: An Approach for Aspect-Oriented Analysis and D
学生
授業
登録
解除
クラスとアスペクトの役割分担
アスペクトがどこまで担当するべきかについ
ては,
未知の部分が多い
AspectJ
は利便性のため,たくさんの言語要素を
取り込んでしまった
型チェックや例外処理など, Java との互換性のため
の制限あり
実装重視で,後付けで理論を固めている傾向が強い
最小限の機能だけを定義したアスペクト指向プロ
グラミング言語を考えようという議論が進行中
プログラミング言語 AspectJ
Java
に,アスペクト記述のための言語要素を追加
アスペクトは,「いつ,何をするか」を指定する
「ポイントカット・アドバイス」という仕組みを導入
用語
ポイントカット : 処理を追加ないし代替する対象
例:「名前が set で始まるすべてのメソッド呼び出し」
アドバイス : ポイントカットに対する操作
例:「直前に,メソッド名を記録するという処理を追加」
AspectJ
におけるアスペクトは,ポイントカットと
アドバイスを定義するモジュール
ポイントカットの指定
ポイントカットはプログラム実行時の「いつ」を指定
ポイントカットは, Join Point の集合として定義される
Join Point:
プログラム実行中のイベント
プログラムの実行は, Join Point の列としてモデル化される
よく使われる Join Point
メソッド呼び出し (call)
メソッドの実行 (execution)
フィールドの参照 (get)
フィールドへの代入 (set)
AspectJ
の場合,クラス名,メソッド名などにワイル
ドカードを許すことで「集合」を効果的に選択できる
アドバイスの指定
ポイントカットで選択された対象(イベン
ト)に対して
ある処理を,その直前に挿入する (before)
ある処理を,その直後に追加する (after)
ある処理で,その対象を置換する (around)
あるポイントカットの直前に処理を実行する場
合:
before() : pointcut_definition { … }
AspectJ
でのロギングの実現例
before(): call(* *.set*(..)) {
Logger.logs(thisJoinPoint.getSignature());
}
「名前が set で始まるメソッドの
呼び出し」を選択
“thisJoinPoint”
は
Join Point
の
コンテキスト情報を保持
3
章 : アスペクトを用いた表明の
記述
表明(アサーション)とは
「特定の時点で成立しているべき条件」の記述
Java
における Assert 文 :
assert ( Boolean expression );
assert(
true
):
正常
ドキュメントとしての表明
表明は,あるコードのまとまり(ブロック
,メソッドなど)が「何をするか」を記述す
る
例 :
double sqrt (int x) {
assert( x >= 0 );
double result = /*
計算 */
assert( result * result <= x );
assert( result * result > x-1 );
return result; }
事前条件
表明の利点
明確な責任の分担を可能にする
契約による設計 (Design by Contract)
契約=メソッド単位での事前条件と事後条件
事前条件は,利用者側への要求
事後条件は,提供される機能
障害の原因がどちらにあるかを切り分けるために使われる
ソフトウェアの早期故障検出
ソフトウェアの障害が他の場所に波及する前に検出す
る
重要なデータなどを壊す前にプログラムを停止できる
デバッグ時,「どこで失敗したか」は有効な情報となる
研究の目的
モジュールを横断した表明をアスペクトで
記述する
必要な言語要素と,その効果を検討
モジュールを横断した表明の例
Observer
パターンに,制約を追加
従来の方法では, Observer のモジュール性を悪化さ
せる
アスペクトを用いて書き換える
Motivating Example: Observer
パタ
ーン
Observer
+ update();
Subject
+ attach(observer);
+ detach(observer);
attach, detach
update
1. observer
は subject に自分を登録する
2. subject
は,自身が変化したとき, observer に通知する
3. observer
は,不要になった時点で登録解除する
例 : 画面 ファイル
ファイルが更新されたら
画面にも反映
1 subject -to- N observers
制約
1 subject – to – N observers
の制約
Observer 1
つが 複数の Subject に接続されるのを禁止
Observer
は接続した相手の情報を保存していない
Subject
は, Observer が既に接続済みか検査できな
い
接続済み
Observer 1
Observer 2
Subject 1
Subject 2
既存の表明による実現
Observer
の接続相手を保存する
subject
フィールドを Observer クラスに追加する
Subject.attach
メソッドを実行したとき,フィールド
が空であることをチェックして,自分自身の参照を
セットする
従来の解決方法の問題点
Observer
クラスのカプセル化が破壊される
Subject
クラスの
attach
メソッド, detach メソ
ッドだけが Observer のフィールドを読み書きし
ている
Observer
クラス側からの書き込みは禁止されてい
る
Observer
Subject
subject
read/write
attach
must not
modify
表明をアスペクトとして分離する
ケーススタディでは,独自の言語を使用
AspectJ
で利用可能な機能のうち,表明の記述に必要
な部分だけ抽出したもの
AspectJ
に変換可能
使用可能な言語要素
「メソッド呼び出し」だけをポイントカットとして選択可能
–
事前条件の評価= 「メソッド呼び出しの前」に assert 文を実行,で
表現可能
– 呼び出し側,呼び出し先,引数にアクセス可能
既存のクラスに,必要なフィールド・メソッドを追加できる
表明検査・それに付随する処理の追加が可能
アスペクトの導入後の形
Observer
へのフィールド追加,
アスペクトによるモジュール性の
向上
関連した表明と,それに必要なメソッド,フィ
ールドを一箇所にまとめることができる
開発者に,それらが表明専用であることを明示し,他
の用途に誤って使われることを防ぐ
Observer
パターンの例では, Observer の接続相手を保存
した subject フィールド
モジュール間の結合度の減少,凝集度の向上
subject
フィールドは,アスペクトの中で定義され,アス
ペクトの中でだけ参照される
Observer
内に定義し, Subject が参照する場合よりも良
い
アスペクトがもたらす有用性
コンテキストに依存した表明の定義が可能となる
例:信頼できないコードからの呼び出しのときだけ厳しい
チェックを行なうアスペクト
十分テスト済みのコンポーネントに対しては,何もチェックしない
呼び出す側に依存した条件をコンポーネントから分離して
いる
A component
Well-tested
Component
Experimental
関連研究との組み合わせ (1/2)
動的アスペクト
実行時に,適用/無効化が可能
特定の処理を行っている間だけ有効化,といった使用
が可能
インスタンスレベルアスペクト
特定のオブジェクトにだけ,アスペクトを適用
する
AspectJ
は,対象をクラス単位で選択する
通常は動的アスペクトとして実装される
関連研究との組み合わせ (2/2)
状態に基づくジョインポイントモデル
オブジェクトの状態(変数の値)を規定
状態遷移の発生に対して,処理を関連付ける
例 : 「スタックが空でなくなるとき」
従来は,「 Stack.push メソッドの呼び出し」を選択
この手法 : 「 Stack.size = 0 から Stack.size > 0 に
なったとき」
Size = 0
Size > 0
スタックの状態定義
状態遷移に
処理を関連付ける
メソッド呼び出し列に関わらず
状態変化だけで指定できる
分散システムなどへの適用可能性
環境整備は進みつつある
分散環境との親和性は報告されている
AspectJ
の場合
分散システムにおけるログ取得のケーススタディが存在
分散環境向けの AspectJ の拡張の提案もなされている
「どのホストで動作しているか」といった動作条件など
AOP Alliance
異なるアスペクト指向システムの相互運用のための
「アスペクト適用」インタフェース定義プロジェクト
実行時オーバーヘッド
AspectJ
コンパイラの最適化技術の進展
各モジュールに手でコーディングした場合と遜
色ない†
ロギングの場合の実験では,最大でも, 10 %程度の
性能劣化
手で書いたコードよりも高速になる場合も
表明で複雑な条件をチェックする場合のコスト
「条件の検査コードを実行するかどうか」が
静的に決定可能かどうかによって大きな影響を受ける
† Erik Hilsdale, Jim Hugunin: Advice Weaving in AspectJ.
3章のまとめ
表明はソフトウェア開発における重要な道具
表明の中には,モジュールを横断するものがある
横断的な表明は,クラスのモジュール性を損なう
横断的な表明をアスペクトとして分離する
関連した表明を1箇所にまとめることが可能にな
る
コンテキストに依存した表明の記述など,柔軟な
使い方が可能
4
章 : プログラムスライシングによるデ
バッグ支援
アスペクト指向の利点
「いつ処理を実行するか」がポイントカット
として明記される
横断的関心事を実行するルールの変更が容易となる
処理の対象となるクラスを簡単に変えられる
開発者は,必要なアスペクトを選んでコンポーネ
ントに適用するだけ
個々のアスペクトを作る人,クラスを作る人,クラスに
アスペクトを適用する人,クラスにさらに別のアスペク
トを適用する人は,同一人物とは限らない
アスペクト間の干渉 (再掲)
例 :
データベースコンポーネントに対して,
「メソッド呼び出しの引数を記録する」アスペ
クトと,
「データベースに渡す文字列引数を暗号化し,
戻り値の内容を復号化する」アスペクトを適用
する
記録される文字列は,暗号化されているべきか
?
Database
Logger
Logging
Encryption
A client
call
アスペクト間の干渉の原因
アスペクトを複数貼り付けたとき,予期せぬ
動作をすることがある
主な要因 :
アスペクトが仮定しているメソッドの呼び出
し順序や,使うデータが,他のアスペクトか
ら影響を受けている
先ほどの例では,暗号化アスペクトが引数のデー
タを書き換えるのと同時に,ロギングアスペクト
が,同じデータを参照している
「干渉」によって起きた問題への
対応
基本的には,動作の順番を決めることで解決す
る
AspectJ
では precedence という宣言を行う
従来のプログラミングでは,メソッド呼び出し文を
並べるときに決定している問題
人間でなければ決定できない
データベースへのメソッド呼び出しの引数の記録は
,暗号化前後,どちらがほしいか,開発者によって異
なる
両方ほしい,という開発者もいるかもしれない
干渉の検出へのアプローチ
理想的には,アスペクトの動作順序の決定が
そもそも必要かどうか自動チェックしてほ
しい
個々のアスペクトの処理内容を調べる手間があ
る
順序決定が必要でないことも多い
しかし,機械的な検出は困難
「同時に動くアスペクト間での干渉」といった条件付
きでの検出がいくつか研究されている
プログラムスライシングの適用
問題が起こってからの対処でのアプローチ
あるアスペクトが,他のアスペクトからどう影響を
受けているかを,機械的に調査して,開発者に提示
する
プログラムスライシングとは
プログラム解析手法のひとつ
プログラム内部の依存関係を解析する
ある変数に対して,影響を与えるプログラム文の集
合を抽出する
アスペクト内の変数を基点にすると,そのアスペクトが
,他のアスペクトから影響を受けていないか調べられる
プログラムスライスの定義
プログラムのある文 s のある変数 v (スライス基
点 <s,v> )の値に“影響”を与えうる文の集合
影響 = 代入-参照 関係, if 文など制御関係
プログラム文を頂点,依存関係を辺としたグラフ探索
基点 < 6, b >
1: a = 5;
2: b = a + a;
3: if (b > 0) {
4: c = a;
5: }
6: d = b;
1: a = 5;
2: b = a + a;
3: if (b > 0) {
4: c = a;
5: }
6: d = b;
a
b
a
b
制御
スライス計算に必要な情報
データ依存関係
ローカル変数の 代入 → 参照
フィールド(メンバ変数)の 代入 → 参照
制御依存関係
実行制御文の条件節 → 制御される文
メソッド呼び出し関係
メソッド呼び出し文 → 呼び出されるメソッドの文
メソッド呼び出し文の実引数 → 呼び出されるメソッドの仮
引数
アスペクトの連動位置 → 動作するアスペクト
アスペクトの連動位置 → アスペクトが参照する実行時点情報
アスペクト指向のための拡張
Class Logger
logs()
Logging
Aspect
Class Line
setColor
Class Circle
setRadius
setColor
Class Line
setColor
Class Circle
setRadius
setColor
Aspect Logging
before_call()
「アスペクトが動作する」
=
対応するメソッドを
呼び出している,とみなす
Class Logger
参照
呼出
動的情報の利用
目的をデバッグに限定
実行が失敗するテストケースが特定されている
状態を想定
動的(実行時)情報
が利用可能
オブジェクトの区別,動的束縛の解決によって
コード量を減らす
スライスツールの実装
統合開発環境 Eclipse への統合
プラグイン形式で機能を追加できる
開発者がエディタ上でそのまま利用できる
コンパイル時にソースコード情報を収集
静的依存情報の収集
実行時情報が存在すれば読み込んで利用
動的解析モジュールを付加して実行しておく必要あ
り
実行時情報がなければ静的情報だけでスライス計算
プロトタイプのスクリーンショッ
ト
スライス基点をエディタ上で選択
スライス結果を
エディタ上に出力
適用実験
1. AspectJ
のサンプルコードに対する適用
5
つのデザインパターンの実装を対象
従来ツールで,どのくらい依存関係の追跡にコスト
がかかるか評価
2.
学生 12 人によるデバッグ実験
AspectJ
プログラムを対象にしたデバッグ作業
4
つのアスペクトのうち 1 つが,他の 1 つの動作を
阻害
12
人中, 6 人が,プログラムスライスの情報を使用
評価 (1/2)
依存関係の追跡作業は,コストが高い
従来のツールは,他のアスペクトが「どこで動
くか」を表示するだけ
影響を与えるようなアスペクトかどうかは,コードを
読まないと分からない
スライシングでは,影響を与えるかどうかも同時に与
えられる
–
「影響を与えない」ところは最初から無視できる
アスペクトは,通常,複数のファイルに定義さ
れるので,ファイルをまたいだ依存関係を接続
していく必要がある
評価 (2/2)
バグの原因特定について
作業に取り掛かる段階で,コードを読む指針となる
「原因の候補」として目をつけた点に対して,その部
分がスライスに含まれているかどうかで,候補を絞り
込める
バグの修正について
変更結果が他のアスペクトに影響を及ぼさないことを
確認するには,他のアスペクトも読まないといけない
スライスだけで,作業時間を短縮できるとは限らない
影響波及解析手法との組み合わせが考えられる
†
† 四野見,玉井 : アスペクト指向における織り込みによる影響波及解析.
4章のまとめ
アスペクト指向プログラムのデバッグ支援
プログラムスライシングの適用
従来手法に,「アスペクト呼び出し」を追加
アスペクトの動作を,メソッド呼び出しと同様の形式で
扱う
静的情報,実行時情報を組み合わせた開発者の支援
評価実験の結果
スライシングは,アスペクトによる振る舞いの変化
を効果的に示すことができる
アスペクトによって引き起こされた問題の特定に有
効
アスペクト指向プログラムの品質
モジュール性などを客観的に評価する指標は?
アスペクトの導入の影響を評価したい
オブジェクト指向での指標には,アスペクトに関する定義
がない
CK
メトリクスの拡張
†
「クラス」 → 「クラスまたはアスペクト」
結合度 : Coupling Between Objects の拡張
1
つのクラスまたはアスペクト中に登場する他のクラス,アスペク
トの数
凝集度 : Lack of Cohesion の拡張
1つのクラスあるいはアスペクト中のメソッド単位で,お互いにメ
ンバー変数をまったく共有しないようなペアの個数(大きいほど悪
い)
† Sant Anna, C., Garcia, A., Chavez, C., Lucena, C. and Von Staa, A: On the Reuse
and Maintenance of Aspect-Oriented Software: An Assessment Framework.
新たな評価尺度の導入
新たな尺度: 関心事の分散度合い
1つの関心事は少数のモジュールで実現されるべ
き
提案は複数
1つの関心事を実装に関わる
クラス・アスペクトの数
+それらを直接参照する
クラス・アスペクトの数
1
つのクラス(アスペクト)が
関わる要求の個数を数える
†
† Kassab, M., Ormandjieva, O. and Constantinides, C.: Providing Quality
Measurement for Aspect-Oriented Software development. Proceedings of
品質の評価ケーススタディ
シミュレータに対する変更操作
†
オブジェクト指向システムに比べ,結合度は大きく低下
1つのメソッドから呼び出されるメソッドの数は増加
する
CK
メトリクスにおける振舞いの複雑さの指標
RFC (Response For a Class) =
呼び出したメソッドから推移的に呼び出すメソッド数
保守性,再利用性は上がる
結合度の低下が大きく貢献する
モジュール数の増加が,理解容易性の足を引っ張
る
個々の部品は単純になっても,部品点数が増える
† Shiu Lun Tsang, Siobhán Clarke, Elisa Baniassad: Object Metrics for Aspect Systems: Limiting
Empirical Inference Based on Modularity. Trinity College Dublin technical report. 2004.
むすび
アスペクト指向プログラミング
「横断的関心事の分離」を提案
モジュール単位「アスペクト」の導入
アスペクトの用途 : Development / Production / Runtime Aspect
Development Aspect
に属する関心事のモジュール化を提案
Development Aspect
は,ソフトウェア開発作業全般で登場するため重要
プログラムの動的解析
オブジェクトを横断した表明
Production / Runtime Aspect
での有用性は,他の研究者によっ
て示されている
横断的関心事のモジュール化にアスペクト指向プログラミング
は有効
アスペクト指向のもたらす複雑さへ
の対処
プログラムスライシングによるデバッグ支援を実現
プログラムスライシングをアスペクト指向向けに拡張
変数の値にアスペクトが影響を与えている場合,それを提示
できる
プログラムスライシングに基づく他の解析手法にも同様
の拡張は適用可能
影響波及解析は既に実現されている
プログラム解析手法を使うことで,アスペクト指向プロ
グラミングの利用が容易となる
問題の発生を予測する方法の研究はまだ途上
型推論,プロセス代数など,理論的側面からの研究
今後の展望
アスペクト指向プログラミングから
アスペクト指向ソフトウェア開発へ
Early Aspects
要求間の依存関係の整理
システムの広範囲に影響を与える要求の発見
Aspect-Oriented Modeling
関心事のモデリング
アスペクト指向プログラムの設計
アスペクトのためのモデル記述言語
Aspect-Oriented Programming
横断的関心事のモジュール化
アスペクトのテスト方法
アスペクト指向の影響
横断的関心事のクラスからの分離
以前よりも単一の部品は単機能に近づく
部品のモジュール性,凝集度,再利用性は向上
コンポーネント間の結合が増加
コンポーネントの結合を管理する必要性が増大
クラスの場合,「メソッド呼び出し」で明示的に結合
されていた
アスペクトの場合,いつ動作するかは,結合対象のプ
ログラムが決まるまで分からない
研究課題
関心事の整理/管理
モデルとソースコードの関連付け
作ったものが,実際にモデルを反映しているか検査
ソフトウェアから,人間が「読める」情報を抽出する
関心事間の関係の可視化
1つのアスペクトが及ぼす影響の可視化は研究されているが
,
複数のアスペクトの関連の可視化は実現されていない
広範囲に影響を与えるアスペクトの振る舞いの可視化も困難
大規模ソフトウェアの抽象化
ソフトウェアの適切な単位への分割
「関心事」ごとに,対応するソフトウェアの要素を発見する
アスペクトの可視化
ある1つのアスペクトに対して,関連する
クラスを表示した場合
Database
Logger
Logging
Encryption
A client
call
Database
A client
call
「横断的関心事」の問題
横断的関心事: 従来のモジュールが対応で
きない関心事
他のモジュールに少しずつ変更を加える必要あ
り
例 : 名前が set で始まるメソッドの呼び出
しを記録
Class Line
setColor
Class Circle
setRadius
setColor
Class Logger
logs()
各メソッドに,呼び出し文が必要
Logger.logs(methodName);
一貫した実装の維持が困難
保守性を悪化させる
アスペクト指向の実現方法
従来のモジュール単位ではまとめられなか
ったものを,
アスペクトにどのようにまとめるか ?
できるだけモジュール間の依存関係を減らした
い
コンパイラがプログラムを組み立てるルールが
必要
Join Point Model
Join Point:
プログラム中の特定の実行時点
プログラムの実行を「 Join Point の列」として
とらえる
メソッド呼び出し,フィールドの参照,更新, ...
Join Point
の決め方が言語の特性を決める
アスペクトの記述方法
アスペクト = 「いつ,何をするか」 で処理を記述
pointcut:
イベント (join point) の集合
advice: pointcut
に対応させる手続き
Pointcut
の直前に処理を追加する
Pointcut
の直後に処理を追加する
Pointcut
の代替の処理を実行する(本来の処理を回避する)
advice
の呼び出しは,コンパイラ・インタプリタが自動で
埋め込む
メソッド呼び出しが,対象のプログラム側に出現しない
アスペクトは,他のクラスにメンバーを追加してよい
クラス階層で関係のないクラスにも同じメソッドをまとめて
定義できる
「図形の移動が起きたら画面を更
新」の例
「図形の移動」というイベントは
メソッド呼び出し
アスペクトを用いた表明の書き換
え
事前条件,事後条件は,アスペクトとして書
きやすい
「メソッド呼び出しの直前と直後に条件を検
査」という
簡潔なルールによって記述が可能
AspectJ
pointcut sqrt_call(int x): call(double aClass.sqrt(int)) && args(x);
による実装例
before(int x): sqrt_call(int x) {
assert( x >= 0 );
}
言語要素の検討 : Join point
Join Point Model
AspectJ
の Join Point Model を採用
AspectJ
のモデルはメソッド呼び出しなど,実行時のイベントに基づ
く
「メソッド呼び出しの前後」が表明の検査が一番多いタイミング
Pointcut: Join point
の選択に使える述語
call pointcut
が主体
Context exposure
も重要
Context exposure:
呼び出しなどの時点でのオブジェクト,引数への
アクセスを提供する仕組み
AspectJ
における
this, target, args pointcuts
アドバイスとインタータイプ宣言
Advice
assert
文を書くのが主な目的
1つの呼び出しに対して,事前・事後条件がペアで付
く
両方をペアで書けるように言語を用意
AspectJ
では before/after と個別で実現される
インタータイプ宣言
表明の記述に必要なメソッド・フィールドの定義
オブジェクトに,中間状態の保存用のフィールドの追加
データ集計用のメソッドの追加
表明 「専用」 であることが明示される
Aspect for Observer
Advice for Subject.detach (
省略 )
インタータイ
プ宣言
(AspectJ
形
式 )
定義の開始
定義の終了
Advice for Subject.attach
Pointcut declaration
this calls
target.method(args)
Preconditions
(before)
code block executed after the postconditions are checked.
The beginning of
advice definition
アスペクトの導入によって生じる
弱点
複数のコンポーネントの表明が,1つのアス
ペクトになる
1つのコンポーネントの表明が,複数のアス
ペクトに分散する
アスペクトは,表明の追加だけが許されている
存在を知らなくても,テスト段階で検知可能
アスペクトの存在は,ツール等で検知可能
横断的な表明をすべて検知するよりも容易
– クラス名など,必要な情報がアスペクト内に提供されているた
め
アスペクト指向での動的解析の実
現
プログラムの動的解析とは
プログラム解析技術に必要な情報を,プログラ
ムの実行時に取り出すこと
メソッド呼び出しの発生順序
変数の代入・参照の発生順序
特定のメソッドの実行回数のカウント
オブジェクトの確保した個数
メソッドの実行時間,…
多数のメソッドに対して,解析用の処理を追加
する必要がある
従来の実現法との比較
通常は,プログラム変換技術を用いる
メタプログラミング技術が必要
構文のパース,構文木上での変換
たとえば,メソッドの先頭にロギング用のコードを追
加する
実行したい処理内容と,実装(変換ルール)に
隔たりが大きい
アスペクト指向による実現
処理内容を明確に表現可能
メタプログラミングの知識がほとんど不要
ケーススタディ
プログラムスライシングに必要な動的解析
モジュールを AspectJ で実装
フィールド参照・代入,メソッド呼び出しで,
実際にどのオブジェクトが使われたか履歴を記
録
イベントを取得するアスペクト + 解析用クラス
+ 結果の圧縮処理クラス
合計で約 1000 行程度のモジュール群として実装
対象プログラムの一部としてコンパイルされる
ので,テスト環境の構築やデバッグ作業が容易
他の方法と比べた場合
Java
コンパイラのカスタマイズ
最適化したコードを生成するといった実装も(努力すれば)
可能
そのかわり,実装に必要なコストが高い
プリプロセッサによる実装
やりたいことを,構文木の変換処理として書き下す必要あり
Java Virtual Machine Debugger Interface
JVM
に付随するデバッガを作るためのインタフェースの利用
スレッド制御やメモリ確保などの分析も可能
そのかわり, JVM の動作に関する知識が必要
JVM
が機能を提供しない場合もある
実験 (1) ツールの適用
適用対象
AspectJ
サンプルコード 5種類
プログラムの実行時情報解析アスペクト
各サンプルコードのサイズは平均 500 行
実験内容
サンプルコードを実行し,その結果に対してプログ
ラムスライスを計算
従来のツールを用いた依存関係の追跡との定性的比
較
AJDE:
どこでアスペクトが動作するかをマーカーで表示
する
実験 (2) 開発への影響の評価
大学院の授業での利用
大学院生 ( 修士課程 ) 12 名
授業で Java 使用経験あり, AspectJ は使用経験なし
開発環境 : Eclipse + AspectJ plug-in
実験の手順
Eclipse
についての解説
Eclipse
を用いた Java プログラムのデバッグ演習(事前課題
1)
AspectJ
についての解説
Eclipse
を用いた AspectJ プログラミング演習(事前課題2)
Eclipse
を用いた AspectJ プログラムのデバッグ(実験)
ランダムで選んだ 半数,6名 にプログラムスライスを渡す
–
時間の都合上,印刷物で提供
対象プログラムの概要
対象 : 式評価プログラム
入出力例 : (+ 4 3 (* 2 7 ) (* 2 7) ) 35
一部のノードは共有されていることがある
クラス5つ(式構造クラス),アスペクト4つ,合計 340 行
処理経過の文字列出力
計算結果の共有 (同じ式が2度目以降は計算を飛ばす)
式のグラフ表現上でのループ検出
評価が終了したグラフの接続解除
アスペクトの干渉によって正しい結果が出力できない
原因: 計算を飛ばすアスペクトによって,文字列出力の処理もスキッ
プされる
プログラムスライス
文字列出力アスペクトの,文字列を格納している変数がスライス基点
他3つのアスペクトのうち,計算結果の共有アスペクトだけが影響する
アスペクトの干渉
計算結果
記録 / 共有
アスペクト
ノード
計算結果
ノード
途中を出力するアスペクト
値の要求
提供したスライスの一部
public aspect CachingAspect {
// member of this Aspect
static private Set workers = new HashSet();
// add a member to Worker class
private boolean Worker.isAlreadyCalculated = false;
pointcut work_call() : call(void Worker.work());
pointcut first_work_call() :
work_call() && !cflowbelow(work_call());
void around(): work_call() {
Worker w = (Worker)thisJoinPoint.getTarget();
if (w.isAlreadyCalculated) return;
else {
proceed();
w.isAlreadyCalculated = true;
workers.add(w);
}
}
// clear the flag when calculation process is finished
after(): first_work_call() {
for (Iterator it = workers.iterator(); it.hasNext(); ) {
Worker w = (Worker)it.next();
w.isAlreadyCalculated = false;
}
workers.clear();
}
}
既に計算済みの場合は
計算を省略する
計算が完全に終了した
時点で,フラグをクリア
この計算省略機能が,
計算経過の文字列出力も
飛ばすことがバグの原因
出力結果には関係ないので
スライスに含まれない
実験の提出物
提出物 (事前の2回の演習課題,実験用の
演習)
問題の原因
修正方針
変更したソースコード
作業に要した時間
スライスを使用した感想
提出した結果を分析
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University