Transcript PPT file

= AOP (Aspect-Oriented Programming)
アスペクト指向プログラミングに
関する十の神話
増原英彦 ([email protected])
東京大学 大学院 総合文化研究科
第37回情報科学若手の会招待講演 2004年9月
1
概要
• AOP入門
– モジュール化の意義
– モジュール化のための既存の技術
– 既存の技術の限界 ―― 横断的関心事
– AOP と AspectJの基本機能
• ポイントカット・アドバイス機構
• 型間宣言機構
• 神話
2
お母さんのためのAOP入門
料理のレシピに見る
横断的関心事
3
プログラムとは
レシピのようなものだ
• 両者とも「どのような順序で
どのような操作を行うか」を記述
ビーフカレーの作り方
材料(4人分):牛肉300g・サラダ油大さじ2・じゃがいも4個・人参
1本・玉葱1個・ベイリーフ1枚・水5カップ・バター大さじ2・カ
レールー1箱
1. 牛肉を一口大に切り、サラダ油を熱した鍋で炒める
2. 1に一口大に切ったじゃがいも、人参を加えて炒める
3. 玉葱をみじん切りにして、バターを熱したフライパンで炒める
4. 1に2を合わせ、ベイリーフ、水を加えて30分煮込む
5. アクをとり、カレールーを加えてさらに20分煮込む
4
レシピはモジュール化されてる!
「決定版 はじめての料理」
モジュール化 = 一連の手順に
名前を付け、別に定義すること
• 使用側では手順の詳細を
気にしなくてよい
• 定義側を独立して変更できる
• 同じ手順が何度も出現する
場合に定義を共有できる
― 変更も1回
void みじん切り(材料) {
1. 材料の皮をむく
2. for a in X,Y,Z
材料をa軸方向に4~5mm
間隔に包丁で切る }
void 皮をむく(材料) {
switch(材料) {
case 玉葱:
1. 1に一口大に切ったじゃがいも、人参を
茶色の薄皮を手でむく
2. 玉葱をみじん切りにして、バターを熱した case 人参:
3. 1に2を合わせ、ベイリーフ、水を加えて30 ピーラーを使って… } }
4. アクをとり、カレールーを加えてさらに20分
5
「みじん切り」の効用
「決定版 はじめての料理」
モジュール化 = 一連の手順に
名前を付け、別に定義すること
• 使用側では手順の詳細を
気にしなくてよい
• 定義側を独立して変更できる
• 同じ手順が何度も出現する
場合に定義を共有できる
― 変更も1回
void みじん切り(材料) {
1. 材料の皮をむく
2. for a in X,Y,Z
材料をa軸方向に4~5mm
間隔に包丁で切る }
7. 1に一口大に切ったじゃがいも、
8. にんにくをみじん切りにして、バタ
9. 1に2を合わせ、ベイリーフ、水を
1. 1に一口大に切ったじゃがいも、人参を
10.アクをとり、カレールーを加えて
2. 玉葱をみじん切りにして、バターを熱した
3. 1に2を合わせ、ベイリーフ、水を加えて30
4. アクをとり、カレールーを加えてさらに20分
6
「みじん切り」の効用
「決定版 はじめての料理」
モジュール化 = 一連の手順に
名前を付け、別に定義すること
• 使用側では手順の詳細を
気にしなくてよい
• 定義側を独立して変更できる
• 同じ手順が何度も出現する
場合に定義を共有できる
― 変更も1回
void みじん切り(材料) {
1. 材料の皮をむく
2. for a in X,Y,Z
材料をa軸方向に4~5mm
間隔に包丁で切る }
void みじん切り(材料) {
1. 材料の皮をむく
1. 1に一口大に切ったじゃがいも、人参を 2. 材料をぶつ切りにして
2. 玉葱をみじん切りにして、バターを熱した ミキサーで混ぜる }
3. 1に2を合わせ、ベイリーフ、水を加えて30
4. アクをとり、カレールーを加えてさらに20分
7
横断的関心事とは
「本格派」のようなもの
• 関心事 = ひとまとまりと考えられる
手順・材料群・コツ・etc.
(モジュール = 関心事を
ひとまとめに記述したもの)
• 横断的関心事 =
モジュールに分けて書いたときに、
複数のモジュールにまたがる関心事
– その関心事は散在してしまう
– 他の関心事はもつれてしまう
8
横断的関心事とは
「本格派」のようなもの普通の
本格派ビーフカレーの作り方
レシピ
材料(4人分):牛肉300g・サラダ油大さじ2・じゃがいも4個・人参1本・玉
葱1個・ベイリーフ1枚・水5カップ・バター大さじ2・カレールー1箱・カ
レー粉大さじ3・トマトジュース200cc・ヨーグルト1カップ・ガラムマサ
ラ適量・ブイヨン3個
void 玉葱を炒める() {
1. 牛肉を一口大に切り、カレー粉小さじ1と一緒にサラダ油を熱した鍋
で炒める
1. 弱火のフライパンでバターを
2. 1に一口大に切ったじゃがいも、人参を加えて炒める 溶かす
2. while (20分過つまで
3. 玉葱をみじん切りにして、バターを熱したフライパンで炒める
飴茶色になるまで)
4. 1に2を合わせ、ベイリーフ、水、ブイヨン、トマトジュースを加えて30
玉葱をかき混ぜる
分煮込む
焦げそうになったときは
5. アクをとり、カレールー残りのカレー粉を加えてさらに20分煮込む
フライパンを火から離し
6. 仕上げにヨーグルト1カップを加え混ぜ、ガラムマサラをかける
火力を調節する
}
9
横断的関心事とは
「本格派」のようなもの
本格派ビーフカレーの作り方
•
散在
材料(4人分):牛肉300g・サラダ油大さじ2・じゃがいも4個・人参1本・玉
葱1個・ベイリーフ1枚・水5カップ・バター大さじ2・カレールー1箱・カ
• もつれ
レー粉大さじ3・トマトジュース200cc・ヨーグルト1カップ・ガラムマサ
1.
2.
3.
4.
5.
6.
ラ適量・ブイヨン3個
void 玉葱を炒める() {
牛肉を一口大に切り、カレー粉小さじ1と一緒にサラダ油を熱した鍋
で炒める
1. 弱火のフライパンでバターを
1に一口大に切ったじゃがいも、人参を加えて炒める 溶かす
2. while (20分過つまで
玉葱をみじん切りにして、バターを熱したフライパンで炒める
飴茶色になるまで)
1に2を合わせ、ベイリーフ、水、ブイヨン、トマトジュースを加えて30
玉葱をかき混ぜる
分煮込む
焦げそうになったときは
アクをとり、カレールー残りのカレー粉を加えてさらに20分煮込む
フライパンを火から離し
仕上げにヨーグルト1カップを加え混ぜ、ガラムマサラをかける
火力を調節する
}
10
AOPとは「本格派」を分けて
書く技術
メリット
本格派の場合
• カレールーのかわりにカレー粉
• 「普通のレシピ」と共存 大さじ3を使う
• 「本格派」を別レシピに • 牛肉はカレー粉大さじ1を加えて
炒める
時間のない場合
• 玉葱を炒めるときは、飴茶色に
再利用
• 玉葱も一口大に切り、他の野菜
マトンカレーの作り方
なるまでじっくりと。焦げそうに
野菜
カレーの作り方
と一緒に炒める
材料(4人分):牛肉300g・サラダ油大さじ2・じゃがいも4個・人参1
なったときはフライパンを火から
ビーフカレーの作り方
材料(4人分):牛肉300g・サラダ油大さじ2・じゃがいも4個・人参1
本・玉葱1個・ベイリーフ1枚・水5カップ・バター大さじ2・カレー
• 炒め終わったら圧力鍋で5分間
材料(4人分):牛肉300g・サラダ油大さじ2・じゃがいも4個・人参1
本・玉葱1個・ベイリーフ1枚・水5カップ・バター大さじ2・カレー
離し火力を調節する
ルー1箱
本・玉葱1個・ベイリーフ1枚・水5カップ・バター大さじ2・カレー
ルー1箱
煮る
1. 牛肉を一口大に切り、サラダ油を熱した鍋で炒める
ルー1箱
• 具を煮込む際に、ブイヨン3個と
1. 牛肉を一口大に切り、サラダ油を熱した鍋で炒める
2.
1に一口大に切ったじゃがいも、人参を加えて炒める
1. 牛肉を一口大に切り、サラダ油を熱した鍋で炒める
トマトジュース200ccを加える
2. 1に一口大に切ったじゃがいも、人参を加えて炒める
3. 玉葱をみじん切りにして、バターを熱したフライパンで炒める
2. 1に一口大に切ったじゃがいも、人参を加えて炒める
3. 玉葱をみじん切りにして、バターを熱したフライパンで炒める
4. 1に2を合わせ、ベイリーフ、水を加えて30分煮込む
• 仕上げにヨーグルト1カップを加
3. 玉葱をみじん切りにして、バターを熱したフライパンで炒める
4. 1に2を合わせ、ベイリーフ、水を加えて30分煮込む
5. アクをとり、カレールーを加えてさらに20分煮込む
4. 1に2を合わせ、ベイリーフ、水を加えて30分煮込む
え、ガラムマサラをかける
5. アクをとり、カレールーを加えてさらに20分煮込む
5. アクをとり、カレールーを加えてさらに20分煮込む
11
以上、
お母さんのためのAOP入門
―本題―
プログラミング言語では?
12
プログラミング言語における
モジュール化とは何か?
「1つ」の操作や値を1まとめにして
インターフェースを決めること
• 1まとめ → 使う側は細部を
忘れることができる
• インターフェース (型・仕様・etc.)
← 「使う側」に対する約束
→ 「中身」を「使う側」と
独立して変更できる
13
モジュール化のための技術
対象
操作
値
操作と値
モジュール
技術
サブルーチン・関数・手続き
構造体・レコード
抽象データ型・クラス・structure
コンポーネント・functor
14
モジュール化の例 (OOP)
• 図形エディタ [Kiczales, et al. 2001]
– 特徴: Illustratorのようなもの
• 「点」「線」「円」などの部品単位で描画・操作できる
• 対話的な描画―移動すると再描画
• モジュール化の方針
– 図形要素をクラスに
– 「移動」「描画」等の操作をメソッドに
16
モジュール化の例 (OOP)
• 図形エディタ
class FigElm {
void moveby(int dx, int dy);
void display(Display d); }
class Display {
static List<FigElm> figures = …;
static void redraw() {display.draw();}
void draw() {
for (fig : figures) fig.draw(d); } }
図形の形による
• 違いを隠す
class Point extends FigElm {
class Line extends FigElm {
•
共通する性質を
int x, y;
Point p1, p2;
「線」の内部表現と
int getX() { return
x; }
Point getP1
() { return p1; }
まとめる
int getY() { … }
Point getP2() { … }
使い方を分離
void moveby(int dx, int dy)
void moveby(int dx, int dy) {
{ x+=dx; y+=dy; Display.redraw(); }
void setX(int x)
{ this.x = x; Display.redraw(); }
void setY(int y) { … }
void draw(Display d) { … } }
p1.moveby(dx,dy); p2.moveby(dx,dy);
Display.redraw(); }
void setP1(Point p1)
{ this.p1 = p1; Display.redraw(); }
void setP2(Point p2) { … }
void draw(Display d) { … } }
17
複雑なデータを1つの
値として扱える
Q: 横断的関心事は何?
• 図形エディタ
class FigElm {
void moveby(int dx, int dy);
void display(Display d); }
class Point extends FigElm {
int x, y;
int getX() { return x; }
int getY() { … }
void moveby(int dx, int dy)
{ x+=dx; y+=dy; Display.redraw(); }
void setX(int x)
{ this.x = x; Display.redraw(); }
void setY(int y) { … }
void draw(Display d) { … } }
class Display {
static List<FigElm> figures = …;
static void redraw() {display.draw();}
void draw() {
for (fig : figures) fig.draw(d); } }
class Line extends FigElm {
Point p1, p2;
Point getP1() { return p1; }
Point getP2() { … }
void moveby(int dx, int dy) {
p1.moveby(dx,dy); p2.moveby(dx,dy);
Display.redraw(); }
void setP1(Point p1)
{ this.p1 = p1; Display.redraw(); }
void setP2(Point p2) { … }
void draw(Display d) { … } }
18
A:図形が変化する度に再描画
class FigElm {
void moveby(int dx, int dy);
void display(Display d); }
縺れ
class Point extends FigElm {
int• x,抽象図形として
y;
int getX
() { return x; }
利用するときに邪魔
int getY() { … }
void moveby(int dx, int dy)
{ x+=dx; y+=dy; Display.redraw(); }
void setX(int x)
{ this.x = x; Display.redraw(); }
void setY(int y) { … } }
class Display {
static List<FigElm> figures = …;
static void redraw() { … } }
散在
• 再描画の
class Line extends FigElm {
方針変更時に
Point p1, p2;
Point getP1
() { return p1; }
変更箇所が沢山
Point getP2() { … }
void moveby(int dx, int dy) {
p1.moveby(dx,dy); p2.moveby(dx,dy);
Display.redraw(); }
void setP1(Point p1)
{ this.p1 = p1; Display.redraw(); }
void setP2(Point p2) { … } }
19
アスペクト指向プログラミング (AOP)
• 横断的関心事をモジュール化する技術
[Kiczales+97]
複数のモジュールにまたがる
操作や構造の記述手段
• 具体的な処理系:
AspectJ [Kiczales+01], 他多数
• 典型的応用:
ログ・デバグ・最適化・
セキュリティ等のモジュール化
21
AspectJ入門: 適用結果
• 図形エディタ
class FigElm {
void moveby(int dx, int dy);}
class Display {
static List<FigElm> figures = …;
static void redraw() {display.draw();}
void draw() {
for (fig : figures) fig.draw(d); } }
描画方針と独立
class Point extends FigElm {
int x, y;
int getX() { return x; }
int getY() { … }
void moveby(int dx, int dy)
{ x+=dx; y+=dy; }
void setX(int x) { this.x = x; }
void setY(int y) { … }}
図形が変化する
度に再描画する
“アスペクト”
class Line extends FigElm {
aspect DisplayUpdating {
Point p1, p2;
pointcut
Point getP1() { return
p1; } move() :
Point getP2() { … } call(int FigElm.moveby(int,int)) ||
void moveby(int dx, call(void
int dy) { Point.setX(int)) ||
Point.setY(int)) ||
p1.moveby(dx,dy); call(void
p2.moveby(dx,dy);}
||
void setP1(Point p1) call(void
{ this.p1 Line.setP1(Point))
= p1; }
void setP2(Point p2)call(void
{ … } } Line.setP2(Point));
after() : move() { Display.redraw(); }
void FigElm.draw(Display d);
void Point.draw(Display d) { … }
…}
22
AspectJの主要概念
• アスペクト (cf. クラス)
横断的関心事をまとめる単位
• アドバイス (cf. メソッド)
動作
追加的な操作
• ポイントカット (cf. シグネチャ)
適用時点を決める
• 型間定義
追加的宣言 構造
23
AspectJの主要概念
•
•
•
•
アスペクト
アドバイス
ポイントカット
型間定義
•aspect
前後に追加する動作
DisplayUpdating {
pointcut move() :
• 置き換える動作
call(int FigElm.moveby(int,int)) ||
cf. CLOS
の before / after /
call(void Point.setX(int)) ||
aroundメソッド
call(void Point.setY(int)) ||
call(void Line.setP1(Point)) ||
call(void Line.setP2(Point));
after() : move() { Display.redraw(); }
moveしたら,その後で
Display.redraw()を呼べ
void FigElm.draw(Display d);
void Point.draw(Display d) { … }
…}
24
AspectJの主要概念
•
•
•
•
アスペクト
アドバイス
ポイントカット
型間定義
moveするとは
FigElm.moveby,
Point.setX, …を
呼び出すこと
aspect DisplayUpdating {
pointcut move() :
call(int FigElm.moveby(int,int)) ||
call(void Point.setX(int)) ||
call(void Point.setY(int)) ||
call(void Line.setP1(Point)) ||
call(void Line.setP2(Point));
after() : move() { Display.redraw(); }
• メソッド呼出・フィールド
void
FigElm.draw(Display d);
アクセス・コンストラクタ
void
Point.draw(Display d) { … }
実行・例外発生・etc.
…}
• 組み合わせ・名前付け
25
AspectJの主要概念
•
•
•
•
アスペクト
アドバイス
ポイントカット
型間定義
FigElmクラスにdraw
メソッドを追加
DisplayUpdating {
•aspect
メソッド・フィールドの追加
pointcut move() :
• 親クラス・実装クラスの追加
call(int FigElm.moveby(int,int)) ||
call(void Point.setX(int)) ||
call(void Point.setY(int)) ||
call(void Line.setP1(Point)) ||
call(void Line.setP2(Point));
after() : move() { Display.redraw(); }
void FigElm.draw(Display d);
void Point.draw(Display d) { … }
…}
26
Java
AspectJの実行モデル
======
class FigElm { … }
p.setX(10);
setX(10)を
呼び出す
Point
x=110
y=3
class Point {
int x, y;
int getX()
void moveby(int,int)
void setX(int) }
class Display { … }
class Line {… }
class Main {… }
aspect DisplayUpdating {
pointcut move() :
call(int FigElm.moveby(int,int)) || …;
after() : move() { … }
void FigElm.draw(Display d);
void Point.draw(Display d) { … }
…}
27
AspectJの実行モデル
fig.draw(d);
p.setX(10);
drawを
呼び出す setX(10)を
呼び出す
Point
x=110
y=3
class FigElm { … }
class Point {
int x, y;
int getX()
void moveby(int,int)
void setX(int) }
画面を
更新
class Display { … }
class Line {… }
class Main {… }
aspect DisplayUpdating {
pointcut move() :
call(int FigElm.moveby(int,int)) || …;
after() : move() { … }
void FigElm.draw(Display d);
void Point.draw(Display d) { … }
…}
ポイントカットに
合致
アドバイス本体を実行
結合点と呼ぶ
追加されたメソッドを実行
28
AspectJの実行モデル
• ポイントカット+アドバイス機構
– メソッド呼び出し等の各動作(=結合点)が
– ポイントカットに合致した場合に
– アドバイスを前,後,あるいは置き換えて実行
• 型間宣言機構
– 各クラス(=結合点)が
– 型パターンに合致した場合に
– メソッド等の宣言が追加されたものとして扱う
29
what’s good? ― ポイントカット!
• FigElm・Point・Line
に対する動作
→ まとめて指定
↓
横断的関心事を
モジュール化!
aspect DisplayUpdating {
pointcut move() :
call(int FigElm.moveby(int,int)) ||
call(void Point.setX(int)) ||
call(void Point.setY(int)) ||
call(void Line.setP1(Point)) ||
call(void Line.setP2(Point));
after() : move() { Display.redraw(); }
…}
30
what’s good? ― ポイントカット!
DisplayUpdating {
• ワイルドカードに aspect
pointcut move() :
call(int FigElm.moveby(int,int)) ||
よって簡潔に
call(* FigElm+.set*(..));
定義できる
: move() { Display.redraw(); }
• 例: FigElmとその after()
…}
子クラスにある
“set”で始まる名前のメソッドが
呼び出されたとき
31
what’s good? ― ポイントカット!
• 複雑な条件も
指定できる
Q: p.moveby(2,3);は
何回redrawを呼ぶ?
A: 3回
1回にするには?
aspect DisplayUpdating {
pointcut move() :
call(int FigElm.moveby(int,int)) ||
call(* FigElm+.set*(..));
after() : move() { Display.redraw(); }
…}
class Point … {
void moveby(int dx, int dy) {
setX(getX()+dx);
setY(getY()+dy); } }
32
what’s good? ― ポイントカット!
• 複雑な条件の例:
「move()の中から
呼ばれたものを除く
move()」
setX
after() : move()
…}
&&
!cflowbelow(move()) { … }
setY
moveby
main
aspect DisplayUpdating {
pointcut move() :
call(int FigElm.moveby(int,int)) ||
call(* FigElm+.set*(..));
class Point … {
void moveby(int dx, int dy) {
setX(getX()+dx);
setY(getY()+dy); } }
33
AspectJ入門: まとめ
• アスペクト: 横断的関心事のためのモジュール
• ポイントカット+アドバイス:
複数のモジュールで起きる動作に対し
動作を追加する機構
• 型間定義
複数のモジュールに対し,
宣言を追加する機構
対象を指定する方法が強力
(e.g.,ポイントカット)
34
AOPにまつわる神話
• AOPの生い立ち
サブジェクト指向
プログラミング
適応的
プログラミング
開放型
実現
自己反映
プログラミング
特定領域向けAOP
(分散・並列・・・)
汎用AOP
35
神話一: AOPはオブジェクト指向
の次に来るパラダイムだ
• プログラム言語は構造化プログラミング→
抽象データ型→オブジェクト指向→
アスペクト指向と進化している
• AOP  オブジェクト指向の置き換え
– むしろ追加的な機構
36
神話二: AOPはOOPの
欠点を改善する技術だ
• クラス・メソッドを使っても
上手くモジュール化できなかったものを
モジュール化するための技術
• OOPに限らず
モジュールのある言語に有効
– AspectC [Coady他02]
– AspectML [Dantas, Walker03]
– レシピ!?
37
神話三: アスペクトととは
従属的なモジュールだ
• 支配的なモジュール: 例) 図形の種類
→ クラスでモジュール化
• 従属的モジュール: 例) 画面更新
→ アスペクトでモジュール化
• 対等なモジュール分割どうしを合成する
という考え方もあるHype/J [Ossher,Tarr01], CME
+
=
38
Hyper/J [Ossher01]
• 関心事ごとにクラス階層を作成
(支配的なモジュールがない)
• 階層どうしを合成して実行
– 合成方法を指定する言語
• 既存プログラムから
関心事を抽出
Observable
moved() {
display.update(this);
}
Display
update(FigElm)
display
Figure
elements
Point
getX()
getY()
setX(int)
setY(int)
moveBy(int,int)
FigElm
Line
getP1()
getP2()
setP1(Point)
setP2(Point)
moveBy(int,int)
Display
update(FigElm)
39
神話四:
AOPは名前ベースの技術だ
aspect DisplayUpdating {
• ポイントカットは
pointcut move() :
メソッドの名前を
call(int FigElm.moveby(int,int)) ||
使って時点を指定
call(* FigElm+.set*(..));
→名前を正しく
after() : move() { Display.redraw(); }
…}
付けないとダメ
• 現状はその通り
• 「意味」に基くポイントカットが研究中
– 呼出し文脈: cflow・実行履歴 [Walker]・将来の呼出し
可能性: predicted cflow [Kiczales03]・データフロー
[河内・増原03]・条件分岐, ループ
40
神話五:
AOPはプログラム変換だ
• アスペクトとは、元のプログラムに埋め込まれて
実行されるコードである
→ つまりAOPはプログラム変換の一種
• コードの埋め込み以上のことができる
– 例: 「setXが実行時にmoveByを経ずに
実行されたときには再描画」
• コード変換に依らない処理系もある
– steamloom:仮想機械による織り込み[Bockisch他04]
– Wool:VMフックによる織り込み[佐藤・千葉・立堀03]
41
神話六: AOPは遅い
• メソッド起動のたびにいちいちアドバイスを
探すのでオーバーヘッドが大きい
• 実際はそうでもない
– コンパイル時にアドバイスを埋め込む
[Hilsdale,Hugnin04][増原・Kiczales・Dutchyn03]
– 静的解析による/実行時の最適化
[Sereni,de Moor03][Hanenberg, Hirschfeld, Unland04]
– オーバーヘッドの計測 [Dufour et al.04]
42
神話七:
AOPはログをとるための技術だ
• それ以外の応用ってあるの?
• ログ以外にも最適化・エラー処理などへの
実際的な応用がある
– FreeBSDカーネルをAOPで分離 [Coady他02,03]
アスペクト: プリフェッチ・クォータ・
スケジューリング
– WebSphereのコードをAOPで分離[Coyler04]
アスペクト: ログ・エラー処理・監視
43
see:
Y. Coady, G. Kiczales M. Feeley and G. Smolyn, Using
AspectC to improve the modularity of path-specific
customization in operating system code, in Proceedings
of ESEC-8 / FSE-9, pp.88-98, 2001,Vienna, Austria.
44
神話八: AOPなんかいらない、
デザインパターンで充分
• 「画面の再描画」は
Subject-Observerパターンで実現可能
• 「実現」はできるが、
– 記述は散在してしまう
– パターンを再利用できない
(AOPなら可能になる場合も[Hannemann他02])
45
神話九: AOPはプログラミングを
難しくする
• AOPで例えば「画面更新」を分離
→Point, Lineの定義から「画面更新」が無くなる
→「画面更新」の影響範囲が特定できない
→誤りを見つけるのが難しくなる
• 開発ツールによる支援
– AJDT [Kiczales他01,…]
• OOPでも同じ議論が可能?
→継承によって一部の定義を子クラスに
→親クラスの定義の影響範囲が特定できない
46
see:
Kersten, Clement, and Harley,
AspectJ Tools - New and Noteworthy, AOSD
2004 Demo.
47
神話十: アスペクトは
リファクタリングで抽出するもの
※ リファクタリング = プログラムの機能を変えずに
構造を改良する技術
• 横断的関心事は,プログラムを作ってみないと
「横断的」かは分からないだろう
• そういう例は多い
• 研究レベルでは,アスペクトの利用を前提とした
開発方法論が提案
– “Early Aspects” / “Aspect-Oriented
Modeling” / Use-case Pointcuts
[Sillito,Dutchyn,Eisenberg,De Volder04]
48
まとめにかえて:
AOPの現状と将来
現状
• 沢山の懐疑論者
– 「便利そうだけど,大きな
プログラムは書けない?」
– 「同じことは××機構で
頑張ればできるよ?」
– 「××には使えないよ?」
将来
 1980年代のOOP
• 沢山の言語・技術が提案
(Smalltalk, C++, Flavors,
バイトコード, JITコンパイ
ル, GC, IDE…)
• 理論よりも実践が先行
• それから「当たり前」にな
るのに10年
当たり前 or 「そういえば昔,
AOPなんてのがあったなあ」
49
プログラミング言語の歴史
1955 Fortran
Lisp
1960 Algol-60, COBOL
現存する最古の言語達
1965
最初のオブジェクト指向言語
1970
1975
1980
1985
モ
PL/1
ジ
ュ
Simula-67
goto有害説ー 階
Smalltalk, C
ル 層
Prolog
Scheme
化 性
・
Smalltalk-80
再
Ada
C++
SML
利
Perl
用
実用的なオブジェクト指向言語
1990 Haskell Python
SOP
Ruby
1995 Java, GoF “Design Patterns”
2000 C#
オブジェクト指向があたり前の時代
AspectJ 0.3AspectJ 1.0 最初の汎用AOP言語
実用的AOP言語
50
情報源など
• 会議・論文誌
– Aspect-Oriented Software Development (AOSD)
OOPSLA, ECOOP, ICSE, FSE, ICFP, …
– Trans. AOSD (Springer)
• ポータルサイト: aosd.net
• メール:
– [email protected][email protected][email protected]
• Kiczales’ talk @ ソフトウェア科学会大会
(2004年9月15日, 東工大)
51
おまけ
52