図1●クラス階層の中に散在する横断的関心事
図1●クラス階層の中に散在する横断的関心事
[画像のクリックで拡大表示]
図2●ビジネス・ロジックへのアスペクトの組み込み
図2●ビジネス・ロジックへのアスペクトの組み込み
[画像のクリックで拡大表示]
図3●アスペクトを織り込むタイミングは二つのタイプがある
図3●アスペクトを織り込むタイミングは二つのタイプがある
[画像のクリックで拡大表示]
表1●アスペクト指向に対応した主なソフトウエア
表1●アスペクト指向に対応した主なソフトウエア
[画像のクリックで拡大表示]

 近ごろ,「アスペクト指向」というキーワードを耳にする機会が増えてきました。「アスペクト指向プログラミング(Aspect Oriented Programming)」,略して「AOP」と呼ばれることもあります。もっとも,「アスペクト指向って何?」と聞かれて正しく答えられる人は,まだ多くないでしょう。オブジェクト指向にすら振り回されている方は,「また~指向?」と拒否反応を起こしてしまうかもしれません。

 しかし,アスペクト指向は何もないところから突然変異的に発生した,得体の知れない概念ではありません。従来のオブジェクト指向に足りない部分を補うものです。さて「足りない部分」とは何でしょうか。

オブジェクト指向ではモジュール化できない機能がある

 現在利用できる主要なプログラミング言語のほとんどは,オブジェクト指向に対応しています。JavaやC++はもちろん,Visual Basic,Perl,PHPのような手軽にプログラミングできる言語でも,オブジェクト指向プログラミングが可能になっています。

 オブジェクト指向の特徴の一つは,「コードの再利用性」です。皆さんおなじみの継承や多態性(ポリモーフィズム)といったオブジェクト指向の概念を利用することで,再利用が可能なモジュール(ライブラリ)を作成できます。

 ただ,オブジェクト指向ではモジュール化が難しい機能も存在します。典型的な例としてよく挙げられるのが,プログラムの動作のログを取る「ロギング」と呼ばれる機能です。一般に,ロギングのコードはクラスの階層関係とは関係なく,アプリケーション内の様々な場所に記述されます。このため,スーパークラスに機能をまとめて,サブクラスに継承するという,いつものオブジェクト指向の手法は使えません*1

 ロギングのように,アプリケーションの様々な場所で横断的に使われる共通の機能を「横断的関心事(Cross Cutting Concern)」といいます(図1[拡大表示])。すなわちオブジェクト指向には,横断的関心事のコードが様々なクラスに散在してしまうという問題があるのです。

横断的関心事をアスペクトとしてモジュール化する

 そこで生まれたのが,アスペクト指向です。「アスペクト」とは「側面」や「様相」という意味です。アスペクト指向を利用することで,オブジェクト指向では解決できなかった横断的関心事のモジュール化を実現できます。

 先ほど例に挙げたロギング機能は,アスペクト指向では図2[拡大表示]のように実現できます。まず,横断的関心事である「ロギング機能」を独立したモジュールとして切り出します。この切り出されたモジュールを,アスペクト指向では「インタセプタ(Interceptor)」または「アドバイス(Advice)」と呼びます。

 切り出されたインタセプタを組み込む場所を特定するのが「結合点(Joinpoint)」の役割です。結合点の集合を「ポイント・カット(Point Cut)」といいます。アスペクト指向では,あらかじめ指定しておいたポイント・カットの部分に,共通機能(インタセプタ)を組み込みます。関連するポイント・カットとインタセプタをまとめて「アスペクト」と呼びます。一般に,アスペクトは設定ファイルやオブジェクトといった形で外部化できるので,オリジナルのロジックはアスペクトの存在を意識する必要はありません。

 アスペクト指向はオブジェクト指向を代替するものではなく,補完するものです。オブジェクト指向がビジネス・ロジックの本筋(縦糸)を記述するものであるのに対し,アスペクト指向はその本筋を横断的に貫く横糸だといえるでしょう。ちなみに,アスペクト指向の世界では,アスペクトを本筋のビジネス・ロジックに組み込むことを「Weave:織り込む」と表現します。

 アスペクト指向の説明ではたいていロギングが取り上げられるため,「ロギングくらいでしか利用できないのではないか」という印象を持っている方がいるかもしれません。しかし実際には,アスペクト指向には様々な応用例が考えられます。例えば,トランザクション処理,コネクション・プーリング,例外処理,モック・オブジェクトを使ったユニット・テストなどです。

アスペクトを織り込むタイミングは二つある

 アスペクト指向に対応したソフトウエアにはどのようなものがあるかを見ていきましょう。アスペクト指向の実装は,インタセプタを織り込むタイミングによって,大きく2種類に分類できます(図3[拡大表示])。

(1)コンパイル型

 独自に用意されたコンパイラを利用することで,コンパイルのタイミングでインタセプタを織り込みます。

(2)クラス・ロード型

 特別な実行環境(コンテナ)を提供することで,実行(クラス・ロード)時にインタセプタを織り込みます。

 (1)の方式には,ロジックのコードとアスペクトとを別々にコンパイルできないという問題があります。半面,実行時に織り込みを行わない分,より高いパフォーマンスを期待できるというメリットがあります。

 一方,(2)の方式では,クラス・ロード時にコンテナやクラス・ローダを介して動的に織り込みを行います。このため,クラスを別々にコンパイルすることが可能で,できたクラス・ファイルをほかの環境で再利用することもできます。ただし,実行時に織り込みを行う分,(1)の方式に比べると一般にパフォーマンスは劣ります。

 アスペクト指向に対応した主なオープンソース・ソフトには(表1[拡大表示])のようなものがあります。今回は,この中からそれぞれの方式を代表する二つのソフトウエアの簡単な使い方を紹介します。アスペクトを織り込む方式が異なると,使い方も大きく異なるからです。

 「コンパイラ型」のソフトとしては,アスペクト指向フレームワークの代表格であるAspectJを取り上げます。もともと米Xeroxのパロアルト研究所(PARC)で開発されていましたが,現在はEclipse.orgプロジェクトが開発を引き継いでいます。表1に挙げたAspectWerkzも近くAspectJに合流する予定で,今後はアスペクト指向フレームワークのデファクト・スタンダードになると見られています。

 「クラス・ロード型」では,2005年9月号の連載第3回でも紹介した軽量コンテナ「Seasar2」を取り上げます。Seasar2は,軽量コンテナであると同時に,アスペクト指向を全面的に取り入れている点にも特徴があります。国産のオープンソース・ソフトであり,日本語ドキュメントが整備されている点も,初心者には大きな魅力です。

 今回は,これら二つの環境を使い,「Hello, World」サンプルに対して簡単なログを表示するアスペクトを織り込んでいきます*2


山田 祥寛(やまだ よしひろ)

千葉県鎌ヶ谷市在住のフリーライター(http://www.wings.msn.to/