アスペクト指向プログラミングの成熟
AOPの最大の長所は単純である。より強力な参照メカニズムをプログラミングに提供することだ。
「これは(AOPは)プログラム内の局所的なスコープに留まらない広い範囲で起こるものを参照する機能です」AOPメソロジとそれを取り入れたAspectJ言語の開発者の一人であるCristina Videira Lopesはそう語った。
90年代半ば、米Xerox PARC(Palo Alto Research Center)研究所のチームによる徹底的な議論が重ねられたAOPが、オブジェクト指向プログラミングのエクステンションとして最初に姿を見せたときに、それを迎えたのは批判ではなく無関心だった。しかし、エンタープライズ規模のJavaベース実装が次々と登場するにつれて、AOPを取り巻く基本思想は浸透してきたようだ。特に、AOPツールが米Sun MicrosystemsのEnterprise JavaBeansを補完し、場合によっては完全に不要にさえしてしまうことにプログラマは気付き始めている。
ニーズ
1980年代末、コンピュータ利用の拡大が生んださまざまなニーズに応えたのがOOPである。グラフィカルユーザインタフェースが複数のウィンドウの作成を要求し、データベース利用方法が複雑化した。そして、データを呼び出すプロセスの数も増えた。
データをそれにアクセスするメソッドと一緒にグループ化し、作業を再利用可能な小さなモジュール群に分割することで、OOPはプログラマを単調な作業の繰り返しから解放した。しかし、プログラマがやがて気付いたのは、このモジュール化をどんなにうまく適用しても、データを扱う同じような機能を何度も何度も書かなければならないことだった。このような機能は、横断的(cross-cutting)機能と呼ばれている。プログラムの本質的な機能とは違い、横断的機能はシステムを横断する形でさまざまなオブジェクトから呼び出される。
AOPは、こういった共通のタスクを1つの場所に置く手段として作られた。もちろん、OOPは再利用性のための存在だ。しかし、OOPの再利用可能コンポーネントは通常は1個のクラスとなる。AOPが違うのは、1個のオブジェクトが複数の継承をサポートできることである。AspectJは、複数の関数を1個のクラスに集めるのではなく、関数(アドバイスと呼ばれる)を取り出してそれらをグループ(アスペクトと呼ばれる)にまとめる。プログラム内のある1か所で、アドバイスが適用されるすべての場所を定義する。
1999年に米Xeroxが出願したAOP概念に関する特許には、こう書かれている。「アスペクトとオブジェクトの対話は、オブジェクトとオブジェクトの対話とも、従来方式、つまりオブジェクトのすべての振る舞いがオブジェクトそのものにカプセル化される(中略)方式を使うその他の従来型プログラミング・パラダイムとも異なる。(中略)AOP環境においては(中略)オブジェクトの振る舞いの一部をアスペクトとしてオブジェクトの外部に定義できるが、オブジェクトがこの振る舞いを使う際には、わざわざ呼び出しを実行する必要はない」
認証、ロギング、スレッドセーフ性、キャッシング、ビジネスルール、境界およびエラーのチェック――これらはAOPで扱える横断的機能のほんの一部である。
「オブジェクト指向技術を使っては、このような機能をモジュール式に実装するのは不可能です」と、『AspectJ in Action: Practical Aspect-Oriented Programming』(7月に米Manning Publicationsから出版予定)の著者Ramnivas Laddadは語る。
認証を例にとって説明してみよう。OOP技術を使って実装すると、認証機能を必要とするモジュールの1つ1つに同じ認証コードを書かなくてはならない。問題のあるやり方だ。認証手続きの変更を迫られた場合に、認証を行うすべてのモジュールの更新が必要になる。AspectJを使って実装すると、変更は1か所で済む。
歴史
1995〜97年頃に、米XeroxのPalo Alto Research CenterでAOPの種が蒔かれた。活動を支援したのは、米国国防総省高等研究計画局(Defense Advanced Research Projects Agency)、米国商務省標準技術局(National Institute of Standards and Technology)、そしてXerox自身であった。リーダーはGregor Kiczalesで、発足時のメンバーは、Lopes, John Lamping、Anurag Mendhekar、Chris Maeda、Jean-Marc Loingtier、John Irwinという顔ぶれである。
Lopesは、論文 『Aspect-Oriented Programming: An Historical Perspective (What’s in a Name?)』の中でAOPの芽生えを振り返っている(この論文は今年後半にAddison Wesleyから刊行される予定の 『Aspect-Oriented Software Development』に収録される)。
AOPは、複雑なソフトウェアに明快なデザイン構造を与える方法を模索した結果として生まれた。当時、分散コンピューティングの発想にプログラマの懸念が高まっていた。計算処理アルゴリズムや基本的な機能を保ったままで、同時性、リアルタイム制約、ロケーション制御、永続性、障害復旧をいかにして扱うかで、開発者は頭を悩ませていた。
解決策をプログラム・コードにじかに組み込むと不必要に複雑になることが経験からわかっていたので、チームは一部の機能を基本プログラム・アルゴリズムから切り離す手段としてメタレベル・プログラミングに着眼した。メタオブジェクトは、オブジェクトが発するメッセージや受け取るメッセージを横から抜き取り、同期制約、リアルタイム設定、移行パラメータ、その他の要素の有無をチェックする。こうすることで、特別な機能に気をとられることなく、基本オブジェクトを書くことができる。
その後、Xerox研究所ではさまざまな言語やツールセットがこの方式に基づいて開発された。RGイメージ処理ソフトウェアは、呼び出したメッセージのループ構造をチェックすることでメモリの使用を最適化しようとする。Annotated MatLab(AML)は、言語プロセッサ用の特殊なディレクティブをコードに追加することで、MatLabの最適化を図る。Evaluation Time Control Meta Languageでは、コードの特定の部分を実行時またはコンパイル時に評価することを言語プロセッサに指示できるディレクティブがサポートされている。
1995年に客員研究生としてチームに迎えられたLopesは、論文執筆の副産物としてDJavaという言語を考案した(”D”はdistributed(分散)を意味する)。この言語の目的は、同時性とリモート・パラメータ引き渡しの2つの問題に対処することだった。
同時性を実現するには、あるオブジェクトが別のオブジェクトのアクティブ化の前に終了することをプログラムがチェックできる必要がある。リモート・パラメータ引き渡しを実現するには、オブジェクトがリモートから呼び出された場合に、あらかじめ選ばれた特定のフィールドだけを引き渡せる必要がある。
「分散プログラムが私たちに見せる姿――たいていはだらしない姿なのですが――それに基づいて、Javaで乱雑に絡み合ってしまった特定の機能の絡まりをほどくため、コードを再編成しようとしました」とLopesは書いている。
しかし、ほかのPARCプロジェクトリーダーらとは違って、Lopesはメタクラス・プログラミングはやり過ぎだと感じていた。コンパイル時処理が実行時モデルよりもうまくいかなければおかしいのである。
「そのことを主張するために、メタクラスを定義し、メタオブジェクトをインスタンス化してそれを基本オブジェクトに1対1で関連付け、基本オブジェクト宛てのメッセージをすべて捕らえ、適切なメタオブジェクト・コードをその時点で実行しなければならないのは、私には下手なやり方に思えました」と、Lopesは書いている。
そこで、そうする代わりにLopesが作ったのは、ディレクティブがクラスから独立して表現され、オブジェクトの操作が名前で参照される、という単純な参照メカニズムだった。これは、オブジェクトが自分の依存関係を明示しなければならないOOPの原則とはかけ離れている。論文でも回想されているとおり、Lopesのモジュールは自分からほかのモジュールに押しかけていくかのようだ。
初めは同時性とリモート・パラメータ引き渡しの2つだけのために実装されたDJavaであったが、PARCチームはすぐにこれをAOPをより高い汎用レベルに押し上げる基盤として見るようになった。ここからAspectJが生まれ、1988年初頭に最初のバージョンがリリースされた。Javaのエクステンションとして作られたAspectJは、ソフトウェア業界にとってAOPの働きを知るモデルとなった。
2000年までには、AspectJコンパイラは数百のクラスを扱えるようになっていた。プロのプログラマは、(大学生や研究者とは対照的に)AspectJエクステンションを使い始めていた。
しかし、ものごとがいつもうまくいくとは限らない。Lopesは、エクステンションの初期バージョンが使いづらかったことを認めている。『American Scientist』誌の2003年3/4月号に掲載された「The Post-OOP Paradigm」という記事には、2人の研究者がAspectJを使ってトランザクション処理システムを構築しようとしたが、限定的な成果しか得られなかったことが紹介されている。この記事を書いたBrian Hayesによると、このシステムに求められた機能は「トランザクションが完全に実行されるか、まったく実行されないこと」であった。
「彼らはこの特性をアスペクトとして明確に分離するのが難しいことに気付いた」と彼は結んでいる。
商用分野
それにもかかわらず、EJB(Enterprise JavaBeans)の普及が進むにつれて、エンタープライズ配備に機能を追加できる分散コンピューティング・フレンドリなAOPベースツールがいくつも登場してきている。デバッグ、強制や検証、ロードバランシング、同期などの機能にAspectJが利用される例も増えている。
Laddadによると、エンタープライズ・ソフトウェアの分野でAspectJを利用するパターンは3つある。1つは、エンタープライズ・ソフトウェアを配備したいが、サーバ・コンポーネントにEJBパッケージは使いたくないケースである。EJBを使うと、プログラムはアプリケーションサーバと強く結合する。将来ほかのサーバに切り替えるか、アップグレードするときに、この結合が互換性の問題を引き起こしかねない。また、この分野でのEJBの強さを特別必要としないエンタープライズ・アプリケーションもあるだろう。
AspectJに興味を抱くもう1つのケースは、EJBにはない機能、たとえばロギングや横断的なビジネスルールなどの機能を求めているEJBユーザである。3番目のケースは、ポリシーの強制を目的とする使い方だ。EJB仕様などのルールに従ったコードであることを保証するために、AspectJを使ってアプリケーションをコンパイルする、というのがこのテクニックである。
「発想はこうです。すべてのルールを掌握する若干のアスペクトを書き、それらを適用してアプリケーションをコンパイルすれば、何か間違ったことをしているコードがあればコンパイラがそれを検出します。独自のエラーチェック・コードを組み込めるというわけです」Laddadによると、有能なプログラマならAspectJの基礎を数日で飲み込めるそうだ。
Lopesの論文では、AOP方式を利用するメリットがあるサンプルの1つとして、電話会議の利用時間と通話料を追跡するプログラムが使われている。複数の参加者がまちまちの間隔でタイマを呼び出すので、ある者は会議の冒頭から呼び出し、ある者はまったく呼び出さず、その他の者は電話会議に参加するときにしか呼び出さない、といったパターンがある。計時機能を呼び出す条件に関する情報を1個のモジュールに収めることができるので、プログラマは基本クラスに手を付けなくてもこの条件を変更できる。
Laddadによれば、AspectJの用途はエンタープライズ・システムに限られない。デスクトップ・ソフトウェア・システムやリアルタイム・システムの開発にも利用できる。
2002年12月、PARCはAspectJをオープンソース・ソフトウェア開発プロジェクト Eclipseに転換させた(ただし、一部の重要な技術はXeroxに特許権がある)。6月6日にリリースされたAspectJ-1.1.0には、新機能として、.jar形式での配布が可能なコンパイル済みアスペクト・ライブラリのサポートやアスペクトを任意の.jarファイルに適用する機能などが含まれている。
取り組むべき問題はまだ残されている。たとえば、プライベート変数へのアクセスをアスペクトに認めるかどうかもその1つだ。アスペクトがプライベート変数にアクセスできるのは「堕落したカプセル化の一種ではないか?」というのが、あるプログラマの意見である。その反面、それができないとAspectJの有効性が制限されるという懸念もある。
この問題の打開策がまだ見つかっていないことをLopesは認める。「この問題については何年も議論が交わされています。どちらにも一理あります」
JBoss
AspectJはAOPと密接に結び付いてはいるが、AspectJ以外にAOPの実装がないと言えばウソになる。最後にチェックした時点で、Aspect Oriented Software Developmentページには、38種類のプラットフォームがリストアップされ、C++、C#、Python、Perl、Smalltalkなどの言語がサポートされている。
商用分野に目を向けると、米JBoss Groupは、同社のJBossアプリケーション・サーバが、AOPフレームワークを使った最初のJ2EEベースのアプリケーション・サーバであると称している。JBossのバージョン4.0は、6月2日にリリースされた。
AOPを採用したことで、JBossはアプリケーション・サーバ市場において一定の競争力を獲得している。バージョン4.0のプレス・リリースによれば、オブジェクト永続性、キャッシング、アシディティ(acidity)、リモート性、トランザクション、セキュリティ・サービスをすべてEJBを書かずに実現できる。また、Javaオブジェクトを書いた後で、開発サイクルの後の段階になってエンタープライズ型サービスを追加することになっても、元のオブジェクトを修正する必要はないという。
白書『Why I Love EJBs』の中で、JBossの創立者Marc Fleuryは、AOPメソロジを使うことで、開発チームがEJBアラカルトを用意することが可能となり、ほとんどのEJBパッケージが提供しない(と彼が言う)モジュール性を提供できたと語っている。特に、スタンドアロンのインターセプタが「入ってくる呼び出しを捕らえ、呼び出しの前後関係(たとえば特定のメソッドのトランザクション属性設定)を見て、自分のロジックを呼び出しに適用する」という。この方法の長所は「ミドルウェア技術をIDEに直接導入できることである」。
「私たちは、望みのインターセプタ・スタックを特定のコンポーネントに指定できるフックを提供する」
Joab Jacksonはメリーランド州Laurelを活動拠点とするフリーライターである。軍事技術の民間転用を推進するNational Technology Transfer Centerに以前は籍を置いていた。