アスペクト指向プログラミングに 関する十の神話

Slides:



Advertisements
Similar presentations
オブジェクト指向 言語 論 第八回 知能情報学部 新田直也. 多相性(最も単純な例) class A { void m() { System.out.println( “ this is class A ” ); } } class A1 extends A { void m() { System.out.println(
Advertisements

ソフトウェア工学 知能情報学部 新田直也. オブジェクト指向パラダイムと は  オブジェクト指向言語の発展に伴って形成され てきたソフトウェア開発上の概念.オブジェク ト指向分析,オブジェクト指向設計など,プロ グラミング以外の工程でも用いられる.  ソフトウェアを処理や関数ではなくオブジェク.
関心事指向アーキテクチャモデリング環 境 Concern-oriented Architecture Modeling Environment 九州工業大学大学院情報工学府 情報科学専攻 鵜林研究室 M1 佐藤 友紀 1.
Web アプリをユーザー毎に カスタマイズ可能にする AOP フレームワーク
九州工業大学 情報工学部 知能情報工学科 鵜林尚靖 2004年10月15日
九州工業大学 情報工学部 知能情報工学科 鵜林尚靖 2005年7月16日
Dynamic AOPと その実装手法について
Myoungkyu Song and Eli Tilevich 発表者: 石尾 隆(大阪大学)
オブジェクト指向プログラミング(2) OOPの三大要素 「クラス」「ポリモーフィズム」「継承」
AspectScope によるアスペクトとクラスのつながりの視覚化
リファクタリングのための 変更波及解析を利用した テスト支援ツールの提案
C#とC++とオブジェクト指向 上甲 健史.
アスペクト指向プログラミングを用いたIDSオフロード
効率的なJava Dynamic AOPシステムを実現する Just-in-Time weaver
アスペクト指向プログラミングと Dependency Injection の融合
遠隔ポイントカット - 分散アスペクト指向プログラミング のための言語機構
AOP言語への 織り込みインターフェイスの導入 A Weaving-Interface for AOP Languages
細かい粒度でコードの再利用を可能とするメソッド内メソッドのJava言語への導入
ソフトウェア工学 知能情報学部 新田直也.
細かい粒度で コードの再利用を可能とする メソッド内メソッドと その効率の良い実装方法の提案
ソフトウェア開発手法の最前線 ~ アスペクト指向、MDA、MIC ~
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
暗黙的に型付けされる構造体の Java言語への導入
関心事ごとに視点を切り替えて プログラムを編集できる 統合開発環境の提案と実装
統合開発環境のための アスペクト指向システム
Javaプログラムの変更を支援する 影響波及解析システム
AspectScope による アスペクト指向プログラ ミングの支援
アスペクト指向に基づく 拡張可能な MDAモデルコンパイラ
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
横断的関心事に対応したオブジェクト指向言語GluonJとその織り込み関係の可視化ツール
豊富な情報を基にした pointcut を記述できるアスペクト指向言語
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第八回 知能情報学部 新田直也.
コードクローン検出に基づくデザイン パターン適用支援手法の提案と実現
クラスのインターフェース やその振る舞いに及ぼすアスペクトの影響の解析と可視化
プログラミング言語論 第四回 理工学部 情報システム工学科 新田直也.
アスペクト指向言語のための 独立性の高いパッケージシステム
アスペクト指向言語のための 独立性の高いパッケージシステム
pointcut に関して高い記述力を持つ アスペクト指向言語 Josh
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
契約による クラスとアスペクト間の 影響解析
プログラムの織り込み関係を可視化するアウトラインビューの提案と実装
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
ソフトウェア工学 知能情報学部 新田直也.
分散 Java プログラムのための アスペクト指向言語
プログラミング言語論 第十一回 理工学部 情報システム工学科 新田直也.
Josh : バイトコードレベルでのJava用 Aspect Weaver
統合開発環境によって表現された 言語機構によるコードのモジュール化
IDE を活用した言語機構に頼らないコード再利用のためのモジュール化
同期処理のモジュール化を 可能にする アスペクト指向言語
計算機プログラミングI 木曜日 1時限・5時限 担当: 増原英彦 第1回 2002年10月10日(木)
様々なAOPメカニズムをモデル化する パラメータ化インタプリタ
アスペクト指向言語のための視点に応じた編集を可能にするツール
プログラムの差分記述を 容易に行うための レイヤー機構付きIDEの提案
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
状況に応じて適切な 例外処理が行なえる アスペクト指向分散環境実験の 支援ツール
開発者との対話を活かした 横断的構造の表現
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
ソフトウェア工学 知能情報学部 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
コードクローン解析に基づく デザインパターン適用候補の検出手法
Javaとは Javaとはオブジェクト指向言語でJava VM(Java仮想マシン)と呼ばれるプログラム上で動作します。
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
GluonJ を用いたビジネスロジックからのデータベースアクセスの分離
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
オブジェクト指向言語論 第十回 知能情報学部 新田直也.
計算機プログラミングI 第10回 2002年12月19日(木) メソッドの再定義と動的結合 クイズ メソッドの再定義 (オーバーライド)
計算機プログラミングI 第5回 2002年11月7日(木) 配列: 沢山のデータをまとめたデータ どんなものか どうやって使うのか
Josh : バイトコードレベルでのJava用 Aspect Weaver
Presentation transcript:

アスペクト指向プログラミングに 関する十の神話 (30mins ECOOP) I’m going to present a modeling framework that explains crosscutting concerns in different mechanisms of aspect-oriented languages BTW, this is a join work with Gregor Kiczales = 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回 void 皮をむく(材料) { switch(材料) { case 玉葱: 茶色の薄皮を手でむく case 人参: ピーラーを使って… } } 1に一口大に切ったじゃがいも、人参を 玉葱をみじん切りにして、バターを熱した 1に2を合わせ、ベイリーフ、水を加えて30 アクをとり、カレールーを加えてさらに20分

「みじん切り」の効用 「決定版 はじめての料理」 モジュール化 = 一連の手順に 名前を付け、別に定義すること 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分

「みじん切り」の効用 「決定版 はじめての料理」 モジュール化 = 一連の手順に 名前を付け、別に定義すること void みじん切り(材料) { 材料の皮をむく for a in X,Y,Z 材料をa軸方向に4~5mm間隔に包丁で切る } モジュール化 = 一連の手順に 名前を付け、別に定義すること 使用側では手順の詳細を 気にしなくてよい 定義側を独立して変更できる 同じ手順が何度も出現する 場合に定義を共有できる ― 変更も1回 void みじん切り(材料) { 材料の皮をむく 材料をぶつ切りにして ミキサーで混ぜる } 1に一口大に切ったじゃがいも、人参を 玉葱をみじん切りにして、バターを熱した 1に2を合わせ、ベイリーフ、水を加えて30 アクをとり、カレールーを加えてさらに20分

横断的関心事とは 「本格派」のようなもの 関心事 = ひとまとまりと考えられる 手順・材料群・コツ・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分過つまで 飴茶色になるまで) 玉葱をかき混ぜる 焦げそうになったときは フライパンを火から離し 火力を調節する }

AOPとは「本格派」を分けて 書く技術 メリット 「普通のレシピ」と共存 「本格派」を別レシピに 再利用 マトンカレーの作り方 本格派の場合 カレールーのかわりにカレー粉大さじ3を使う 牛肉はカレー粉大さじ1を加えて炒める 玉葱を炒めるときは、飴茶色になるまでじっくりと。焦げそうになったときはフライパンを火から離し火力を調節する 具を煮込む際に、ブイヨン3個とトマトジュース200ccを加える 仕上げにヨーグルト1カップを加え、ガラムマサラをかける 時間のない場合 玉葱も一口大に切り、他の野菜と一緒に炒める 炒め終わったら圧力鍋で5分間煮る 材料(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入門 ―本題― プログラミング言語では?

プログラミング言語における モジュール化とは何か? 「1つ」の操作や値を1まとめにして インターフェースを決めること 1まとめ → 使う側は細部を 忘れることができる インターフェース (型・仕様・etc.) ← 「使う側」に対する約束 → 「中身」を「使う側」と 独立して変更できる

モジュール化のための技術 対象 技術 操作 サブルーチン・関数・手続き 値 構造体・レコード 操作と値 抽象データ型・クラス・structure モジュール コンポーネント・functor

モジュール化のための技術 対象 技術 操作 サブルーチン・関数・手続き 値 構造体・レコード 操作と値 抽象データ型・クラス・structure モジュール コンポーネント・functor 要因にきれいに分解された 解をもたないような問題は, しょせん本当の意味で満足には 解決できない問題なのだ (Dijkstra,1972)

モジュール化の例 (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) { … } }

問題: 横断的関心事 1まとめに扱いたいものなのに モジュールをまたがるもの 既存のモジュール化技術では 避けられない: 1まとめに扱いたいものなのに モジュールをまたがるもの 既存のモジュール化技術では 避けられない: ※ 「関心事」と呼ぶ 「線を移動する」機能 ― Line.movebyメソッド 「点」というデータ ― Pointクラス 「変化があると再描画する」機能 ― 横断的

アスペクト指向プログラミング (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. メソッド) 追加的な操作 型間定義 追加的宣言 動作 構造

moveしたら,その後で Display.redraw()を呼べ 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()を呼べ

moveするとはFigElm.moveby, Point.setX, …を 呼び出すこと 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. 組み合わせ・名前付け

FigElmクラスにdrawメソッドを追加 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の実行モデル p.setX(10); setX(10)を 呼び出す Point x=1 y=3 10 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

AspectJの実行モデル fig.draw(d); p.setX(10); 画面を 更新 drawを 呼び出す setX(10)を 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を呼ぶ? 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()」 setX 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はオブジェクト指向の次に来るパラダイムだ プログラム言語は構造化プログラミング→ 抽象データ型→オブジェクト指向→ アスペクト指向と進化している AOP  オブジェクト指向の置き換え むしろ追加的な機構

神話二: AOPはOOPの 欠点を改善する技術だ クラス・メソッドを使っても 上手くモジュール化できなかったものを モジュール化するための技術 OOPに限らず モジュールのある言語に有効 AspectC [Coady他02] AspectML [Dantas, Walker03] レシピ!?

神話三: アスペクトととは 従属的なモジュールだ 支配的なモジュール: 例) 図形の種類 → クラスでモジュール化 従属的モジュール: 例) 画面更新 → アスペクトでモジュール化 対等なモジュール分割どうしを合成する という考え方もあるHype/J [Ossher,Tarr01], CME + =

Hyper/J [Ossher01] 関心事ごとにクラス階層を作成 (支配的なモジュールがない) 階層どうしを合成して実行 合成方法を指定する言語 既存プログラムから 関心事を抽出 FigElm Point getX() getY() setX(int) setY(int) moveBy(int,int) Line getP1() getP2() setP1(Point) setP2(Point) Figure Display update(FigElm) elements display match Point.setX with Observable.moved match Point.setY with Observable.moved match Line.setP1 with Observable.moved match Line.setP2 with Observable.moved Observable moved() { display.update(this); } Display update(FigElm)

神話四: 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 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]

当たり前 or 「そういえば昔,AOPなんてのがあったなあ」 現状 沢山の懐疑論者 「便利そうだけど,大きなプログラムは書けない?」 「同じことは××機構で頑張ればできるよ?」 「××には使えないよ?」 将来  1980年代のOOP 沢山の言語・技術が提案 (Smalltalk, C++, Flavors, バイトコード, JITコンパイル, GC, IDE…) 理論よりも実践が先行 それから「当たり前」になるのに10年 当たり前 or 「そういえば昔,AOPなんてのがあったなあ」

プログラミング言語の歴史 Simula-67 Smalltalk-80 Java, GoF “Design Patterns” 1955 Fortran 現存する最古の言語達 Lisp 1960 Algol-60, COBOL モジュール化 PL/1 1965 最初のオブジェクト指向言語 Simula-67 1970 goto有害説 階層性・再利用 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言語

情報源など 会議・論文誌 ポータルサイト: aosd.net メール: 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日, 東工大)

おまけ

AOP機構の共通性 A&B are parallel EFFB - means of effecting A - program B - program EFFA IDB IDA- means of identifying weaving happens at X X - computation or program XJP- join point

開発支援ツール 既存のソフトウェアからアスペクトを抜き出せる? Yes, 発見ツールが 研究されています see: JQuery [Jansen,De Volder03] FEAT [Robillard, Murphy02] CME see: Jan Hannemann and Gregor Kiczales, Design Pattern Implementation in Java and AspectJ, OOPSLA2002,pp.161-173