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