アスペクト指向のバリエーション解説ということで、これまで4回にわたって連載記事を書いてきたが、今回が最終回となる。第1回「アスペクト指向の基礎とさまざまな実装」ではアスペクト指向の中心的概念となる「横断的関心事の分離(Separation of Crosscutting-Concern)」や「ポイントカット」「アドバイス」といった用語の説明を交えながらAOPの概要を説明し、その後の連載ではアスペクト指向プログラミング(AOP)の代表的な実装としてeclipse.orgの「AspectJ」、JBoss Groupの「JBossAOP」、そしてBEAシステムズもスポンサーとなっている「AspectWerkz」(Codehause)の簡単な使い方を紹介してきた。アスペクト指向の理解には、その概念だけではなく実際にコーディングを体験してみることが一番の近道である。そのため、できるだけ読者が自分で動きを確かめることができるように各実装のセットアップ方法とサンプル・コードを紹介してきたが、最終回となる今回の記事ではコーディングから少し離れ、これまでの総括的な内容とすることで締めくくりたいと思う。
2005年3月の14〜18日にかけて、アスペクト指向ソフトウェア開発(Aspect-Oriented Software Development)の国際的なカンファレンス「AOSD.05」がシカゴで開催された。このカンファレンスにはBEAやオラクル、IBMといった大手ベンダ、そして現在のソフトウェア開発における最先端のテクノロジをリードするTheServerSide.COMなどがスポンサーを務めることとなり盛況に終わったようだ。
しかしながら、アスペクト指向に関する盛り上がりはいっときに比べると少し落ち着きを取り戻した感がある。だからといって、やはりアスペクト指向も一過性のブームでしかなかったのかと考えるのは早計だ。もの珍しさだけで話題に取り上げられることは少なくなったとしても、標準的な技術へと確実に歩みを進めている。
そのほかAOPの実装に関しては、前回「AspectWerkz」の利用法」にも少しお伝えしたが、AspectJとAspectWerkzのコラボレーションによる「AspectJ5」というプロジェクトがeclipse.orgで開始されている。また、最近話題の軽量コンテナ「Spring Framework」においても、Spring AOPと呼ばれる機能が盛り込まれている。こちらについての詳細は、少し前に連載が始まった「Spring Frameworkで理解するDI」でいずれ取り上げられるので、そちらに譲るとしよう。
ここで少し「AOP Alliance」についても触れておきたい。AOP Allianceはアスペクト指向環境(AOE)における共通のアーキテクチャを策定する団体である。連載でも紹介したように、現在AOPにはさまざまな実装が存在し、アーキテクチャの統一は図られていないが、実装間の互換性を高めるためにもベースとなるアーキテクチャの策定は必要だろう。
具体的に、AOP Allianceでは次の3階層のアーキテクチャを定義している。
それぞれのコンポーネントは図1に示すような関係で表される。
現時点ではAOP Allianceの策定内容はドラフト段階ではあるが、近いうちに正式リリースされることだろう。
さて、ここでもう1度アスペクト指向プログラミングの効果的な適用事例を紹介しておこう。これまでの連載では単純な「Hello, World」サンプル・プログラムを通して簡単なアスペクト指向の実装をコードとともに紹介してきたが、あくまでもそれはスタートアップ・サンプルでしかなく、実際のアプリケーション開発にAOPを適用するためにはもう少し踏み込んだスキルの習得が必要である。
世間では、アスペクト指向といえば「ロギング」ばかりが取りざたされており、かくいうこの連載の最初でもロギングの例を紹介した。アスペクト指向の取っ掛かりとして、ロギングの例は最も簡単に説明でき、かつ実際に適用しやすい例だからである。そのような背景から、アスペクト指向の世界を少しだけのぞいてみた人たちにとっては、AOPは結局ロギングだけにしか適用できないのかといった疑問も生じることだろう。
しかしながら、アスペクト指向は決してロギングだけにしか適用できないわけではない。ロギング以外にも、アスペクト指向を適用すれば効果的な例はたくさんあるので、その中から代表的なものをいくつか紹介しておこう。なお、ここでは実装コードは紹介しないが、興味のある人は自身でいろいろと試してもらいたい。
オブジェクト・キャッシングとは、アプリケーションから頻繁にアクセスされるデータをメモリ上に保持しておく仕組みを提供することによってパフォーマンスを向上させるための機構である。また、キャッシュしたオブジェクトのライフサイクル管理やそのほかの高度な機能を提供するものをプーリングと呼ぶこともある。特に、パフォーマンスのボトルネックとなりやすいデータベース・アクセスに関する処理ではキャッシングやプーリングが頻繁に利用されることとなる。
オブジェクト・キャッシングの実装では、メモリの大量消費と同期化に関する問題を常に考慮しなければならない。また、場合によってはキャッシュのオン/オフを動的に切り替える必要があるかもしれない。このような場合にも、AOPを採用することでキャッシングやプーリングに関する処理部分を開発者から完全に隠ぺいし、かつ必要に応じて容易にキャッシュのオン/オフを切り替えることができるようになる。
アプリケーション・フレームワークや、J2EEに代表されるようなアーキテクチャ・プラットフォームを使用する場合には、多くの規約や仕様を順守しなければならない。しかし、プログラムがこのような規約や仕様に違反したとしても、言語仕様にさえ違反していなければ、そのコードがコンパイル・エラーにはならないことはしばしばある。そしてそのようなコードはアプリケーションを稼働させた際に実行時エラーとなって顕在化する。
従来であればこの問題に対しては、個々のプログラマのスキルを信頼するか、規約を強制するラッパー・コンポーネントを作成したりフレームワークの縛りをきつくしたりすることで解決策を見いだしてきた。しかし前者はあまりにも属人的な解決方法であり、後者は余計な制約とストレスをプログラマに与えてしまうことになる。
AOPは実行時の振る舞いだけではなく、コンパイル時におけるこのような「規約の強制」つまりポリシー・エンフォースメントを実現する手段をも提供する。規約をアスペクトとしてウィービングすることで、規約に従わないコードをコンパイル・エラーとしてはじくことが容易に実現できるようになる。
ソフトウェア開発においてコンポーネントの単体テストが重要であることに異論を挟む余地はないだろう。単体テストとは、文字通りコンポーネントそのものをテストするわけではあるが、われわれが強く望むのとは裏腹に、そのコンポーネントだけで処理が完結してしまうようなものはそう多くはない。特に、EJBに代表されるような特定のコンテナ上で動作させることを前提としたアーキテクチャを採用する場合には、コンポーネントの単体テストは一筋縄ではいかなくなる。
このような要件での単体テストにはMockオブジェクトが使われることも多い。Mockオブジェクトは本番環境における特定の状態を作り出す疑似的なオブジェクトである。Mockオブジェクトを使うことで、テスト対象となるコンポーネントを本番環境に配置せずとも単体テストを実行することができるようになる。
このような単体テストにおいてもAOPを採用することができる。結果として、テスト・ケースごとにコンテキストに依存するような状態を作り出すMockオブジェクトを簡単に提供できるようになる。テスト状況に応じて、モジュール化されたMockオブジェクトを注入できるようになれば、単体テストの実行と運用管理の容易性が向上することになるだろう。
システムにアクセスするユーザーに対して、権限のセットであるロールを付与することでアクセス制限や利用可能な機能の制限を課すような手法を「ロールベースのセキュリティ」と呼んでいる。この実装では、ロールの確認や認証処理といったコードはしばしば複数のモジュール間に散在してしまう。しかしながらこういった機能はセキュリティに関するものだけに、なるべく一元管理できることが望ましい。システムにとって、ひいてはその企業にとって生命線とも呼べるようなセキュリティに関するコードを、横断的に散在させてしまうわけにはいかないだろう。そして、このような「横断的関心事の分離」はAOPにとってまさに真骨頂である。
ここで紹介したものはほんの一例にすぎないが、それ以外にもトランザクション管理や永続化などでもAOPは有効に活用できるだろうし、ほかにも面白い使い方がたくさんあるだろう。ぜひ、さまざまな場面でAOPの活用を検討していただきたい。
それでは最後にアスペクト指向とAOPに関して、もう1度まとめておきたい。これまでにも嫌というほど耳にしてきたと思うが、アプリケーション開発においてアスペクト指向を取り入れる最大の目的は「横断的関心事(Crosscutting-Concern)を分離する」ことである。ではなぜ、横断的関心事を分離しなければならないのか? アプリケーションの保守性を向上させ、そして堅牢性と拡張性という、しばしばトレードオフとなる要件を満たすシステムを作り上げるためである。
アスペクト指向が登場した当初は多くの人が誤解をしていた。「オブジェクト指向に代わる新しいパラダイムが登場したらしい」と。しかしながら、アスペクト指向はオブジェクト指向の代わりではなく相互補完の関係にある。
アスペクト指向はオブジェクト指向に取って代わるものではなく、オブジェクト指向の足りない部分を補完するパラダイムである。
現在のソフトウェア開発の主流が「オブジェクト指向開発」であることはおそらく間違いないだろうし、この流れは今後も当分変わることはないと思われる。オブジェクト指向がソフトウェア開発の世界でここまで受け入れられることとなった背景には、それ以前の開発手法に比べて「関心事」をうまく分離できたことが要因の1つとして挙げられるだろう。オブジェクト指向は「振る舞い」と「状態」を1つのオブジェクトにカプセル化し、それぞれのオブジェクトに明確な「役割(ロール)」を与えるという手法で「関心事」を分離することに成功した。しかしながら、連載第1回「アスペクト指向の基礎とさまざまな実装」で説明したように、オブジェクト指向だけでは「関心事の分離」が不十分であり、そのことがソフトウェアの保守性やコンポーネントの再利用性に悪影響を与えている。その元凶は、コード間に散在してしまう「横断的関心事」である。
そしてアスペクト指向は、オブジェクト指向ではうまく分離することが難しい「横断的関心事」を分離する手段を提供する。つまり、あくまでもオブジェクト指向をベースに、さらなる「関心事の分離」を推し進めるのがアスペクト指向の目指すところである。もし、うまく「横断的関心事」の分離ができさえすれば(あくまでも“うまく”というのがポイントではあるが)、そうでない場合に比べて保守性と再利用性が飛躍的に向上することはいうまでもない。
アスペクト指向は、オブジェクト指向によって実現された「関心事の分離」を、「横断的関心事の分離」というさらなる高いレベルで推し進める。
ここで、何をアスペクトとして定義するのかも重要になってくる。ビジネス・ロジックをアスペクトとして定義することも可能ではあるが、どちらかといえば非ビジネス・ロジック、つまりアプリケーションにおけるサービス・レベルの機能を提供するロジックをアスペクトとして定義することが、より効果的であるといえるだろう。それらの機能は再利用の必要性が高く、かつ横断的に散在してしまう可能性が高いからである。さらにいうならば、システムに対してプラグインとして柔軟にアスペクトを追加でき、オン・デマンドでオン/オフの切り替えができれば理想的である。
結果としてシステムは、AOPにより次のようなメリットを享受することができるようになる。
アスペクト指向はまだまだ発展途上であり、実際のソフトウェア開発での適用事例は非常に少ない。しかしながら、現在のソフトウェア開発が抱えるさまざまな問題点を解決するための1つのソリューションを提供し、オブジェクト指向がソフトウェア開発に与えたインパクトと同じくらいのインパクトをもたらす可能性を秘めていることは確かではないだろうか。
今後も引き続きアスペクト指向の動向には注目していきたい。今回の連載では入門的な紹介にとどまったが、また機会があれば実際の適用事例やその効果、問題点などを紹介できればと思う。
米山学
株式会社 クロノス 専務取締役兼CTO。クロノスでは、J2EEや.NETを用いたシステム構築におけるテクニカル・コンサルティングや技術支援、オープンソース・プロダクトの導入支援、技術書籍の執筆、技術教育などに力を入れている。
Copyright © ITmedia, Inc. All Rights Reserved.