アスペクト指向 非機能要件を別枠に |
アスペクト指向は,クラスの本質とはかかわりのない機能を外に切り出すことに主眼を置いている。クラスの本質とは,そのクラスに固有の機能である。例えば商品クラスなら,商品データを取り扱う機能がそのクラスの本質になる。企業システムの分野で,機能要件と呼ばれる部分である(図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サイトで公開している。もちろんソースコードは一切変更していない。