図5●アスペクト指向</B><br>アスペクトは,複数のクラスにまたがる横断的な機能を切り出したもの。そのクラスに固有の機能,本来持つべき機能はオブジェクトに実装する。ロギングやトランザクション管理など,システム全体の都合を考えたときに必要となる汎用的な機能が,アスペクトとして切り出される。
図5●アスペクト指向</B><br>アスペクトは,複数のクラスにまたがる横断的な機能を切り出したもの。そのクラスに固有の機能,本来持つべき機能はオブジェクトに実装する。ロギングやトランザクション管理など,システム全体の都合を考えたときに必要となる汎用的な機能が,アスペクトとして切り出される。
[画像のクリックで拡大表示]
図6●AspectJでの記述例&lt;/B&gt;&lt;br&gt;点(Point)と線(Line)を表現するクラスがあったとする(左)。どちらも移動のメソッドを持ち,最後に画面を更新する処理を実行している。そこで図形の移動を実現するメソッドに対して,共通のアスペクトを適用する。これをAspectJで記述したのが右のリストである。アスペクトを適用するプログラム中の場所は「pointcut」と呼ばれ,「move」という名称で定義されている。「after」以降で,アスペクトとして処理する本体部分を定義する。この結果,各クラスが持つ図形の移動メソッドが呼ばれたあとに,自動的に画面の更新が実行される。アスペクト指向の提唱者Gregor Kiczales氏の講演資料より引用。
図6●AspectJでの記述例</B><br>点(Point)と線(Line)を表現するクラスがあったとする(左)。どちらも移動のメソッドを持ち,最後に画面を更新する処理を実行している。そこで図形の移動を実現するメソッドに対して,共通のアスペクトを適用する。これをAspectJで記述したのが右のリストである。アスペクトを適用するプログラム中の場所は「pointcut」と呼ばれ,「move」という名称で定義されている。「after」以降で,アスペクトとして処理する本体部分を定義する。この結果,各クラスが持つ図形の移動メソッドが呼ばれたあとに,自動的に画面の更新が実行される。アスペクト指向の提唱者Gregor Kiczales氏の講演資料より引用。
[画像のクリックで拡大表示]
画面●WhiteDog System&lt;/B&gt;&lt;br&gt;お絵かきソフトなどのクライアント・アプリケーションを,アスペクト指向プログラミングを用いてネットワーク対応にする。右下のお絵かきソフトにマウスで線を描くと,左上にも同じ線が描かれる。
画面●WhiteDog System</B><br>お絵かきソフトなどのクライアント・アプリケーションを,アスペクト指向プログラミングを用いてネットワーク対応にする。右下のお絵かきソフトにマウスで線を描くと,左上にも同じ線が描かれる。
[画像のクリックで拡大表示]
図7●WhiteDog Systemの仕組み&lt;/B&gt;&lt;br&gt;例えばお絵かきソフトにおいて,ユーザーがマウスをクリックしたときに発生するイベントを,アスペクトの適用場所として指定しておく。その時に実行される処理として,マウスクリックの結果を描画エリアに反映する処理をWhiteDog Systemのオブジェクトが横取りし,WhiteDog Systemサーバーに通知するという処理を記述しておく。サーバーは通知を受け取ると,同じセグメント内に存在するお絵かきソフトに対し,同じ処理を実行するよう通知する。Javaのリフレクション機能(バイナリ・コードからクラスのメソッドや属性などの定義情報を取得し,利用する機能)を利用することにより,元のプログラムを書き換えることなくネットワーク対応機能を追加できる。
図7●WhiteDog Systemの仕組み</B><br>例えばお絵かきソフトにおいて,ユーザーがマウスをクリックしたときに発生するイベントを,アスペクトの適用場所として指定しておく。その時に実行される処理として,マウスクリックの結果を描画エリアに反映する処理をWhiteDog Systemのオブジェクトが横取りし,WhiteDog Systemサーバーに通知するという処理を記述しておく。サーバーは通知を受け取ると,同じセグメント内に存在するお絵かきソフトに対し,同じ処理を実行するよう通知する。Javaのリフレクション機能(バイナリ・コードからクラスのメソッドや属性などの定義情報を取得し,利用する機能)を利用することにより,元のプログラムを書き換えることなくネットワーク対応機能を追加できる。
[画像のクリックで拡大表示]

アスペクト指向
非機能要件を別枠に

 アスペクト指向は,クラスの本質とはかかわりのない機能を外に切り出すことに主眼を置いている。クラスの本質とは,そのクラスに固有の機能である。例えば商品クラスなら,商品データを取り扱う機能がそのクラスの本質になる。企業システムの分野で,機能要件と呼ばれる部分である(図5[拡大表示])。

 しかしクラスにはしばしば,機能要件以外の機能(非機能要件)が混入する。システム全体を動作させるために必要な機能だ。ログ出力や,トランザクション制御などの処理がこれに該当する。

 非機能要件がクラス内に混入すると,大きく二つの問題が発生する。一つは,クラスがそのシステムに対して依存してしまうこと。クラスが純粋に機能要件だけで成り立っていれば,同じ機能を要求する他のシステムでも使い回せるかもしれない。しかしログ出力の形式が違うと,他にはそのまま持っていけない。

 もう一つは,保守性の低下である。例えばログ出力やトランザクション制御は,業務アプリケーションのさまざまな場面で必要とされる。これが複数のクラスに分散していては,保守が面倒になる。例えばログ出力の形式が変わった場合,すべてのクラスを変更しなければならない。

 アスペクト指向では,このような機能をひとまとまりにしてクラスの外に切り出す。複数のクラスに共通するものなので,一つにまとめた方が保守が楽になる。同じコードが複数のクラスに混在していては手直しが面倒になるし,ミスが起こりやすい。

 クラスには,アスペクトに関する記述は一切入らない。アスペクトは,指定したクラスに対して必要なときに外部から適用される。

共通の処理をアスペクトとして記述

 クラスからアスペクトが完全に分離されることは,実際にそのソースコードを見るとよく分かる。図6[拡大表示]は,アスペクト指向の提唱者として知られる,加ブリティッシュ・コロンビア大学教授のGregor Kiczales氏が開発したアスペクト指向言語「AspectJ」(現在はEclipse Foundationが開発)を使って記述した例である。

 図形を表現する二つのクラス,Point(点)と線(Line)がある。どちらもFigureElementから継承した移動のためのメソッド「moveBy」を持つ(図6左[拡大表示])。移動という動作は,点と線のどちらにとっても本質だからだ。

 ところがオブジェクトの状態が変わっただけでは,画面は変わらない。状態を変えたあとに画面を更新する必要がある。しかし画面の更新については,個々のオブジェクトが関知すべきことではない。

 したがって,画面の更新はアスペクトとして別途定義すべきである(図6右[拡大表示])。アスペクトには,アスペクトを適用すべきメソッドと,実行すべき処理(ここでは画面を更新する操作)を定義している。

結合のための技術でもある

 別の見方をすると,アスペクト指向は「依存性のない部品同士を結合する」(東京工業大学の千葉助教授)ための技術でもある。結合技術としてアスペクト指向をとらえれば,クラスに任意の機能を付け加えるために利用するという発想が生まれる。「アスペクト指向は,既存のシステムの拡張手法としても有効な技術」(オージス総研 技術部 ソフトウェア工学センター サイエンティストの藤井拓氏)。

 アスペクト指向に基づいてプログラムを書けば,元のクラスのソースコードを1行も変更せずに,任意の動作を追加できる。当初はバラバラに作られた部品同士でも,あとからやや強引に結合させることが可能になる。これが「アスペクト指向プログラミングは一種の飛び道具」(電通国際情報サービスの比嘉氏)と言われるゆえんだ。利用の仕方によってはとても便利な道具となる。

 そのよい例が,アントラッドの中口孝雄主幹研究員が開発する「WhiteDog System」。元のアプリケーションのソースコードを1行も書き換えることなく,ネットワーク対応機能を追加できるシステムである。ネットワーク機能が追加されたアプリケーションを同一ネットワーク上で複数起動しておくと,それらの状態が自動的に同期する。つまり一つのアプリケーションに対して操作を加えると,同じ操作が他のアプリケーションにも伝えられる。お絵かきソフトを起動して絵や文字を書くと,別のパソコンで同じソフトを起動している人の画面にも同じものが描かれる(画面[拡大表示])。

 WhiteDog Systemでは,「ユーザーの操作を,サーバーを介して他のアプリケーションに伝える」処理を一つのアスペクトとして定義している(図7[拡大表示])。ユーザーがお絵かきソフトに対してマウスを操作すると,本来その操作はアプリケーションの中のオブジェクトに伝えられる。しかしWhiteDog Systemは,ここにアスペクトを挿入する。WhiteDog Systemのオブジェクトが処理を横取りし,アプリケーションに操作が加えられたことをサーバーに通知する。サーバーは通知を受け取ると,同一ネットワーク上に存在するWhiteDog Systemのオブジェクトに通知する。こうして,各アプリケーションの状態が同期する。

 ユーザーの操作を横取りするだけなら,Javaの「Proxy」クラスを利用するという方法もあった。「しかしProxyクラスを利用しようとすると,アプリケーションのソースコードを書き換えなければならない。アスペクト指向技術を使えば,ネットワークに関連するソースコードをアプリケーションから完全に切り離せる」(アントラッドの中口氏)。

 つまり,別の開発者が作成したアプリケーションに対しても,任意にネットワーク機能を追加できることになる。実際に中口氏は,フリーの3次元描画ソフトとして知られる「Teddy」(開発は東京大学大学院情報理工学系研究科コンピュータ科学専攻講師の五十嵐健夫氏)などに,ネットワーク機能を追加した例をWebサイトで公開している。もちろんソースコードは一切変更していない。