「ふんふん。ルールに従って特別に作ったオブジェクトがコンポーネントだ,ってことですね」
「まあ,そうだね」
「その,ルールによって違いってあるんでしょうか」
「うん。全然違う,って言ってもいいくらいだね」

共通アーキテクチャに基づく

 具体的なコンポーネントとして思い浮かべやすいのは,Visual BasicやDelphiなどの開発ツールの「ツールパレット」だろう。ここにグループごとに並べられたアイコンが,それぞれコンポーネントなのである。GUI部品だけでなく,データベース接続,ネットワークなどさまざまなものがある。

 コンポーネントを実現するには,コンポーネントを管理するための仕組みが必要である。これが「コンポーネント・アーキテクチャ」とか「ソフトウェア部品化の規約」などと呼ばれるものだ。

図3●コンポーネントに求められる要素

 これらからコンポーネントに求められる要素を抽出すると,大きく四つある(図3[拡大表示])。まず当然ながら,独立した機能を備えていること。次が自分自身が持つインタフェースを公開できること。これができないと,ほかのプログラムに利用してもらうことが難しくなる。また標準的な通信規約を使っていないと,ある特定の開発ツールに依存したコンポーネントや,アプリケーション・ソフトに特化したコンポーネントとなってしまって,汎用性がなくなってしまう。このように限定した用途であったら,必ずしもコンポーネントの形を採っていなくても実現可能である。最後がこれまた当然であるが,外部から呼び出し可能であること。呼び出すためのインタフェースが存在しなければ,ソフトウェア部品として利用できないのは明白である。

 こういったコンポーネント規約の代表といえるものが,ActiveXコントロール(OCX)とJavaBeansである注5)。この両者,「ソフトウェアを部品化する」というコンセプトは共通しているものの,そのアプローチはかなり違う。

 もう少し具体的に見ていこう。先ほどコンポーネントの要件として挙げた4項目のうち,規約のレベルで定めていなければならないのがインタフェース公開のための仕組みと,通信の仕組みである。これらの違いが,それぞれの規約を特徴づけている。

 例えばActiveXコントロールの場合,インタフェースに関する情報は基本的に実行時に取得する。このため,すべてのActiveXコントロールは「IUnknown」と呼ぶインタフェースを実装していなければならない。元々ActiveXコントロールの仕組みは,複合文書アーキテクチャとして作られたものである。複合文書では,任意のアプリケーションが連携して動作しなければならない。つまり相手が誰なのか,どんなデータをどういう形式で渡すのかなど,事前に決めておくことができないのである。このためOLEの中心には,さまざまなインタフェースやそもそも何者なのかなどを問い合わせるインタフェースとして「IUnknown」が存在するのだ。ActiveXコントロールの場合はさらに,プログラミング言語を特定しないことも求められている。このため,個々のプログラミング言語とは関係のない独自の呼び出し手順を定めている。

 一方JavaBeansの場合,デザイン・パターンによる自動認識と「BeanInfo」と呼ぶインタフェース記述ファイルを使う二つの方法を利用できる。デザイン・パターンとは,似た傾向のものを記述するときに基本原則である。JavaBeansでは,メソッド名などのパターンをあらかじめ決めておいて,そのパターンに合致したものをインタフェースとして抽出する。このように別途インタフェース定義をせずとも,コンポーネントを定義できるのは便利だ。

 ただ頻繁に再利用するようなコンポーネントの場合,BeanInfoファイルを記述してコンポーネントを定義すべきだろう。例えばちょっと複雑なプロパティを持つコンポーネントを持つときに,その値を編集する画面をカスタマイズしたい場面は少なくないだろう。また開発ツールに組み込んで利用する際,ツールパレットに表示するアイコンを変えるにはBeanInfoファイルの記述が必要となる。画面が同じだとツールパレットでコンポーネントを識別できなくなってしまう。

メソッド呼び出しをRPCに変換

 コンポーネントを呼び出す方法は,見かけ上どちらもオブジェクトのメソッド呼び出しにしている。ActiveXコントロールではCOM(Component Object Model)の規約に基づいた呼び出しである。これは,リモート手続き呼び出し(RPC:remote procedure call)を拡張したものといえる,JavaBeansではメソッド呼び出しそのものを使う。

 RPCとは,別のマシンで動作する手続きを呼び出すメカニズムである。ターゲットとなるコンピュータの所在地を含めて,手続きを指定するのが一般的だ。この仕組みをオブジェクト指向向けに仮想化したものが,COMであり,CORBA(Common Object Request Broker Architecture)である。

COMの呼び出し方は3種類

 COMの場合,コンポーネントを呼び出すときの動作形態が三つある。(1)コンポーネントのユーザーとコンポーネントが同じプロセスで動作する場合,(2)同じマシンだがそれぞれ別のプロセスで動作する場合,(3)ネットワークに接続した別のマシンでそれぞれ動作する場合,である。当初COMは,(2)の動作モデルしか備えていなかった。同じマシンで動作するため,LRPC(Lightweight RPC)と呼んでいた。

 ActiveXコントロール(正確に言えばOCX)が登場したころ,OLEは「遅い」といわれていた。当時OLE対応のアプリケーションの代表がWordとExcelであり,OLEを使って複合文書を作るとこれら重たいアプリケーションを同時に動かすということになっていたのだ。またOLE自体もオーバーヘッドとなっていたのは間違いない。だからOLEベースのコンポーネントといったら,まず遅くて使い物にならないだろうというのが通り相場だった。

 そこで登場したのが,(1)の同じプロセスで動作するモデルである。「InProcサーバー」などと呼ばれている。簡単に言ってしまえばDLLとして実装したコンポーネントである。RPCのようなオーバーヘッドがかからないぶん,性能は高い。また当時のWindowsの動作環境では,二つのアプリケーションを同時に動かすのはメモリー的に厳しかった。コンポーネントを呼び出すたびにプロセスを切り替えていたのでは,そのたびにハードディスクにプロセスをスワップアウトしたりするようになりかねない。コンポーネントとして実用的に使えるようにするために,InProcサーバーを使えるようにしたのである。

 そして最後の(3)は,DCOM(Distributed COM)と呼ばれるものである。CORBAへの対抗という意味合いもあった。ネットワークに接続した別のコンピュータで動くサーバー・オブジェクトに対して依頼を発行できるものである。クライアント側のプログラムは,そのオブジェクトを最初に指定するときを除けば,同じマシンで動いているのとまったく同じに取り扱うことができる。

(北郷 達郎、八木 玲子)