アスペクト指向って?

アスペクト指向プログラミングの目的

アスペクト指向プログラミング(Aspect-Oriented Programming)の目的は, 「横断的関心事をモジュール化する」ということにあります.

従来,オブジェクト指向プログラミングならオブジェクトという単位で, 手続き的プログラミングなら手続きという単位でシステムの分解を行っていました.

現在普及しているオブジェクト指向プログラミングは, データ構造とそれを取り扱う手続き群をまとめてオブジェクトとして扱い, またそれらを継承を用いるなどして階層化して整理することができます.

しかし,たとえばオブジェクトという単位だけではうまく分離できない場合 というのが存在することも確かです. たとえば,発生したエラーをすべて記録したい, 現在のネットワーク接続状態をチェックしておきたい,といった要求です. これらの要求は,その処理に参加するオブジェクトに 直接的な関係(たとえばクラス階層での親子関係)は存在しないため, 各オブジェクトに個別に処理を書き加える必要が生じます.

このような,従来のモジュール分解の枠組みでは 分解できないものを「横断的関心事」と呼びます.

アスペクト指向プログラミングは,横断的関心事をどうにかして モジュールとして表現しよう,というものです. 要求分析時あるいは設計時に生まれた関心事が 各モジュールに分散して暗黙的に実現されるのではなく, 明確に1つのモジュールとして分離した状態で表現できれば ソフトウェアの保守性や理解容易性が上がるであろう,と期待されています.

アスペクト指向プログラミングの例

ここでは,AspectJ を用いたアスペクト指向プログラミングの例を示します.

Javaに対するアスペクト指向拡張の一つであるAspectJでは, プログラムの実行時点(Join Point)情報を使って, 「プログラムの特定の実行時点で行うべき処理」をモジュールとして 分離できるようにしています.

AspectJ を用いたアスペクト指向プログラミングの特徴は, 「暗黙の処理実行」にあります. つまり,元のプログラムコードを書き換えることなく, 特定の処理を実行することができます. たとえば,ロギング処理は,本来次のように記述されます.

class Hoge {
  void foo() {
    logger.log("Hoge.foo");  
    // do something
  }
}
class Fuga {
  void bar() {
    logger.log("Fuga.bar");
    // do something
  }
}

これをアスペクトを用いて,次のように書き換えることができます.

class Hoge {
  void foo() {
    // do something 
  }
}
class Fuga {
  void bar() {
    // do something
  }
}
aspect Logger {
  before() : execution(void Hoge.*()) || execution(void Fuga.*()) {
    logger.log(thisJoinPoint.getSignature());
  }
}

AspectJ での実現では,「クラス Hoge のメソッドの実行」というイベントを execution(void Hoge.*()) という述語(ポイントカット)で捕らえて,その直前で実行すべき手続き(アドバイス)を関連付けています.

AspectJ を用いたアスペクト指向プログラミングの特徴を 一言で表現しようとするなら, 一つの極論として,「処理をいつ呼び出すかを呼び出される側に書く」ものだと 考えることができます.

横断的関心事のいくつかは,特定のルールに則った処理です. たとえばネットワークにアクセスする直前に接続状態をチェックするとか, エラーが起きたらデータベースを確実にロールバックしておくなどです. このような処理を,アスペクトとして 「こんな処理をする時には一緒にこの作業もしておいて」と指示を与えることで, クラス階層などにとらわれない処理の記述が可能となります.

アスペクトはなぜ有利?

アスペクトの利点はどこにあるのでしょうか. もしアスペクトがないと,次のような問題に出くわすことになります.

  • 処理が複数箇所に分散するので,後になって仕様が変わる (たとえば引数が増えたりする)と,すべてのコードを変えなければならない.
  • プログラマが,処理を追加するべきでない場所に追加してしまう.
  • プログラマが,処理を追加するべき場所に追加し忘れる.
  • プログラマが,処理として誤ったコードを追加してしまう.
  • プログラマが,誤って本来のプログラムを壊してしまう.

アスペクトを用いて「同時に変更する処理を1つのモジュールにまとめる」ことで, 上記のような問題に対処することができます. 要求の変化に対して,1つのモジュールを変更するだけで済むことから, プログラム開発に必要なコストの削減につながります.

プログラムにコードとして既に分散した 横断的関心事を検出,管理する作業をサポートする ツールも研究されていますが,複数の横断的関心事が絡み合った場合への 対処は困難なものとなっています. アスペクトを用いると,複数の関心事が絡み合った場合のシステムの振る舞いを 整理しやすくなる,という効果も期待されます.

アスペクトはどう使える?

アスペクトの利用方法については別にまとめています.

アスペクトをどう作る?

アスペクトの作成方法については別にまとめています。

アスペクト指向の特徴

アスペクト指向プログラミングの特徴は, 次のように説明することができます.

「プログラム P に対し,条件 C が成り立つとき,アクション A を実行する」
In programs P, whenever condition C arises, perform action A.

たとえば AspectJ の場合, プログラム P としてプログラム実行時のイベント列を, 条件 C としてプログラム実行時のイベントを使い, アクション A としてアドバイスという特殊な手続き呼び出しを使っている, ということになります.

一方で,Hyper/J におけるハイパースライスは, プログラム P としてソースコードファイル群(ハイパースライス), 条件 C としてソースコードの特定の構造(メソッドの名前の一致など)を取り, アクション A としてモジュールの合成という操作を プログラムの実行前に適用しています.

プログラム P ,条件 C とアクション A の選び方にはかなり幅があり, その決定がプログラミング言語・環境の性質を決めることになります.

上記のようなメカニズムの本質はどこにあるのか,というので 色々と議論があり,現在は次のように定義されています.

アスペクト指向 = Obliviousness + Quantification

この定義については,まだ議論も多くあるのですが, 少なくともこの2つの性質を「併せ持つ」ことが アスペクトの重要な特徴であるとされています.

Obliviousness とは

"oblivious" とは,"aware" と反対の意味を持つ言葉で, 「忘れっぽい,忘れている,気づいてない」という意味です.

通常は構文的な意味で, 「対象プログラムの中には,アスペクトの要素への直接的な参照がない」という 状態を指して使われます. 実際には,開発者が「アスペクトが作用してくることを期待して」 特定のアノテーションを付加したり, 特定の命名規則に従ってコードを書くことがある可能性はあります.

一方で,「開発者はアスペクトがどう作用するかを気にしなくてよい」という 意味合いもあるようです(このあたりは,人によっても考え方が違うようです). ロギングや性能計測のように,「あってもなくてもプログラムは正しく動く」タイプの アスペクトというのは,意味的にも "oblivious" であると言えるかもしれません.

Quantification とは

「プログラムの複数の場所(あるいは実行中のタイミング)を指定する」概念のことを指します.

Quantification のもっとも単純な(ただし oblivious ではない)例は メソッド呼び出しです. メソッド呼び出し文は,実行のあるタイミングを指定していて, 実行環境は,メソッド呼び出し命令に到達したら, 対応するメソッドを実行しています.

また,メソッドに様々なアノテーションを持たせるというのも, アノテーションの名前を使ってプログラムの要素を選択できるため, Quantification の一種だといえます.

AspectJ のポイントカット記述は, 複数の実行タイミングを選択するにあたって, 対象プログラム側を変更せずにいられる(oblivious な状態を保てる)点が 従来のメソッド呼び出しなどの quantification と異なっています.

アスペクト指向プログラミングに関する他のウェブサイト

日本語の情報は色々ありますので,読み比べてみてください.

@IT における「アスペクト指向のバリエーション解説」
http://www.atmarkit.co.jp/farc/rensai/aspect01/aspect01.html

IBM developer Works: アスペクト指向プログラミングで、モジュール性を改善する
http://www-06.ibm.com/jp/developerworks/java/020405/j_j-aspectj.html

東工大の千葉先生による解説
http://www.csg.is.titech.ac.jp/~chiba/notes/aop03/index.html

大阪大学井上研究室のサイト(書いてる人間が同じなので内容的にはこことあまり変わりません)
http://sel.ics.es.osaka-u.ac.jp/research/aspect/


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2006-12-24 (日) 16:57:31 (4226d)