使うべきか使わざるべきかDCOM有効活用法

福岡寿和 FUKUOKA, Toshikazu 
富士通SSL 


 COMとDCOMはよく同一視されます.DCOMが分散COMを意味するのですから,当然と言えば当然です.少々乱暴ですが,ActiveX EXEをリモートに配置するか否かがCOMとDCOMの違いであるともいえるでしょう.しかし,COMとDCOMでは,その技術が内因している問題点やクリアしなければならない技術的な課題が大きく異なります(DCOMにおける認証の煩雑さ,COM+の出現からわかるように複雑化しすぎてしまったCOM).COMについていえば,このような問題点はCOM以外の技術も多かれ少なかれ内包しているものですし,COM使った製品が実際に流通している点を考えると現実的なソリューションとしての魅力も備えています.しかし,DCOMはどうでしょうか.現実的なソリューションとしての魅力はあるのでしょうか.そこで今回は基本に立ち戻って,どのような局面でCOM/DCOMを使うのかを探ると共にCOM/DCOMを使わないときの限界を考えてみたいと思います.

COMを使わない方法
   

 COMを使う利点として,モジュールの再利用性が取り上げられますが,ソースコードが提供されているときなどは,実際にCOMを使うほどのこともありません.ソースコードが提供されているときの,モジュールの再利用性を向上する方法は目新しいものではありませんが,COMを使った再利用性向上方法とコンセプトは同じ物です.

図1:フォームモジュール分割

モジュール分割〜フォームモジュール
 大規模なプログラムを作成するときには,機能単位にモジュールを分割し,そのモジュール単位で作成してゆく方法が取られます.モジュール分割と聞くと「難しそう」と思うかもしれませんが,VisualBasicを使っていれば,画面を分割することで,自然にフォームモジュール分割を行なってくれます.モジュール分割の観点から見れば,画面に含まれる機能は単一である方がよく,それは直感的でわかりやすい画面構成であることを意味します.以上のことを踏まえると,VisualBasicを使った一番簡単なモジュール分割方法は,フォームモジュールの分割であるといえるでしょう(図1).
 フォームモジュールの分割を行なうときに注意しなければならないのは,どのようにフォームモジュール間で情報をやり取りするかです.標準モジュールにパブリック変数を定義して,複数のフォームモジュール間で利用する方法もありますが,今回は,クラス化の事を考慮して,パブリック関数やパブリックサブルーチンをフォームモジュールに定義し,その関数やサブルーチンを経由して情報をやり取りする方法を紹介します(リスト1,リスト2).


 このように,フォーム単位であれば,自然とモジュール分割とモジュール共有が行なえるでしょう.これは,1画面=1機能というくくりが直感的に理解しやすいからだと思います.ですから,まずはフォームモジュール分割を通して,モジュール分割の勘を養うのもよいかもしれません.

モジュール分割〜標準モジュール
 本格的なアプリケーションをプログラムしていると,ひとつのイベントの中に複数の機能を含める必要があったり,複数のイベントで共通的な機能を含める必要があったりします.このようなときは,それぞれのイベントの中にすべての機能を記述するのではなく,機能ごとに関数やサブルーチンに分割して,イベントの中では,その分割したものを呼び出すように記述し機能を階層化します(図2).そして,ある範囲の機能ごとに標準モジュールを作成します.もちろん,なるべく標準モジュール間の依存性は疎であり(パブリック変数やパラメタが少ない),標準モジュール内の依存性は密であるのが理想的ですが,フォームモジュールとは異なり,かなり意識して作成しないと理想とするものからは無意味にずれてしまうので,気をつけて分割してください.

図2:機能の階層化

vbpの一括コンパイル
 ソースコードレベルのモジュール再利用で問題になってくるのは,あるモジュールを修正したときに,そのモジュールを使っているプログラムについて,実行ファイルを再コンパイルしなければならないことです.Visual Basicのプロジェクトを構成するファイル(vbp,bas,frm,clsファイルなど)が少ないときには,さほど問題になりませんが,大規模開発などを行なっていて,構成するファイルが1000や2000という数になってくると再コンパイルは一大事業になってしまいます.また障害発生状況を管理していると,構成モジュールが変更されていないのに無闇に再コンパイルすることで実行ファイルのファイル更新日付を変更したくありません.エクスプローラ上で右クリックをしてファイルのプロパティを表示し,バージョンを確認すればよいのかもしれませんが,バージョン確認の第一歩としてファイル更新日付の整合が保たれているのは重要なことです.
 話が横道にそれてしまいますが,Visual Basicマガジン誌上で古橋氏が指摘していたように(1996年4月発売Vol.6 品切),Visual Basic 4.0のセットアップウィザードは,その肝心のファイル更新日付をウィザード利用日時に書き換えてしまいます.そのため,セットアップウィザードを使ったアプリケーションをインストールして,自分のPCの環境がよくわからない状況に陥ってしまう現象が時々見られます.私はどんなに素晴らしいソフトウェアでもインストーラがセットアップウィザードで作られているものは導入しないことにしています.
 さて,ファイル更新日付を考慮しつつ再利用を行なうためには,実行ファイルよりもそれを構成するファイルが新しいときのみ再コンパイルするような方針をたてなければなりません.依存ファイルを使って,Visual C++付属にnmakeやフリーソフトのmakeプログラムを使う方法もありますが,依存ファイルのメインテナンスも大変なことがあります.そこで,Visual Basicを使って,Visual Basicのプロジェクトを構成するファイル(vbp,bas,frm,clsファイルなど)が実行ファイルよりも新しいときは,再コンパイルするプログラム(Vbmake.exe)を作成しました.VB4用とVB5用にわかれていますがロジックなどはまったく同一です.ただし,ActiveXコントロールをVisual Basic自体で作成しており,複数のVisual Basicプロジェクトが依存関係にあるときはコンパイル順番などを意識しなければならず,そのためにはVBPファイルの解析を再帰的に呼び出すなどのロジックを工夫しなければなりません.今回は,そこまでの対応がなされていないので,VBMake暫定版となっています.

VBMakeの使い方                                COLUMN
図3,4:VBMake動作画面、要再コンパイル

1.ファイル・開くでVBPが含まれているディレクトリを設定
2.実行・依存関係チェックで再コンパイルが必要かチェック (図3・4)
3.実行・開始で再コンパイル
4.ファイル・ログを出力で再コンパイル結果をレポート化 (リスト3)


    リスト3:レポート出力
     D:\user\VBM\VBM9809\VBMake\VB5\VBMake.Vbp Check
      VBMake.frm
      Option.frm
      DirSel.frm
       VBMake.exe Completed

バージョン間の互換性                             COLUMN
 ご存知の方も多いと思いますが,ActiveXコンポーネント(DLL,EXE,Documents,Control)には,CLSIDというIDが振られます.OS自体はこのCLSIDでコンポーネントを認識しています.Visual Basic開発環境の[プロジェクトプロパティ]-[コンポーネント]タグで[バージョン間の互換性]をバイナリ互換にして,コンポーネントの実行ファイルとVBPファイルを関連づけておかないと,ファイルサーバー上などにソースコードを配置していたときなどには,マシンが変わるごとに新しいCLSIDが振られ,レジストリ上に不要なCLSIDが増加してしまいます.一度でも実行ファイルを作成したときは,必ずバイナリ互換を指定してください(図8).この指定さえしておけば,インターフェイスなどが変更されない限りは,同一のCLSIDであり続けます.  図8:バージョン間の互換性

COMを使う局面
   

 ソースコードが手元にあるときは,COMを使うよりもVisual Basicのプロジェクトファイルにモジュールを追加して,一枚岩の実行ファイルとすることができました.しかし,ソースコードが手元になかったり,開発言語が異なっているためにひとつの実行ファイルにすることができない状況では,COMなしでは何も始まりません.
 また,一部分だけ入れ替えて,何種類もの製品を作るときも同様です.このときは,ソースコードが手元にあるのですから,それぞれ実行ファイルを作れば良さそうですが,同一ファイル名で機能が異なる実行ファイルを並行開発/管理してゆくのは,ともすれば配布ミスによる障害発生の原因になります.共通機能部分と個別機能部分をCOMで接続して,製品ごとにチョイスできるようにします.

COMを使う局面
マルチDB対応アプリの作成(その1)

 MDB,SQL ServerとOracleに対応したアプリケーションを作成するとき,DAO/Jetにより問題解決するケースが多いようです.しかし,本来は,

 ・MDB         :DAO/Jet
 ・SQL Server  :RDO
 ・Oracle      :Oracle Objects for OLE

がそれぞれに適したミドルウェアです.DAO/Jetにこだわるのではなく,ActiveX DLLを作ってミドルウェアをラッピングすることでマルチDB対応アプリケーションを作成するのがよいでしょう.

DAO/Jet対応版を作成する
 DAO/Jet対応版のクラスモジュールを含んだvbpファイルと共通機能部分のvbpファイルをプロジェクトグループにします(図5).このとき,DAO/Jet対応部分とプロジェクトグループは,共通機能部分と別ディレクトリにしておくのがよいでしょう(図6).
 共通機能部分のvbpでは,DAO/Jetのプロジェクトを参照設定することで,クイックヒント(図7)やパラメータヒントを活用できます(リスト4).本来,共通機能部分のvbpで参照設定を行なうと,その参照先の個別対応部分専属になってしまうので参照設定は行ないませんが,ある程度プログラムが完成してから参照設定を外せば問題ありません.なお,参照設定フォームに表示される内容ですが,同一プロジェクトグループ内では,ActiveXDLLのvbpが参照設定の対象となり[プロジェクト名]が一覧に表示され,他のプロジェクトグループからはActiveX DLLのdllが参照設定の対象となり[プロジェクトの説明]が一覧に表示されます.
 DAO/Jet対応版のActiveX DLLは,ひとつのクラスモジュールとひとつのフォームモジュールから構成されています.フォームモジュールはMDBの選択を行なう画面です.DLLのロジックの中心であるクラスモジュール(リスト5)には,

 (1)  データベース領域を確保.
   クラスの外からの参照はないので,プライベート変数
 (2)  DBと接続する機能:lngLogon
 (3)  結果セットを解放する機能:lngClose
 (4)  DBを解放する機能:lngLogoff
 (5)  カラム数を返却する機能:lngColCount
 (6)  結果セット生成機能:lngCreateDynaset
 (7)  列の値を取得する機能:strFIelds
 (8)  カーソル位置を判断する機能:blnEof
 (9)  カーソルを移動する機能:subMoveNext

の機能があります.


図5:プロジェクトグループ
図6:ディレクトリ構造
図7:事前バインド時のクイックヒント

共通機能部分も汎用化する
 リスト4では,DAO/Jet対応コンポーネントを参照設定することで,Visual Basic 5.0の編集サーポート機能を使うことができました.しかし,このままでは他のコンポーネントと簡単に切りかえることができません.そこで,SetステートメントにNewを指定して,クラスの新しいインスタンスを生成するのを止めて,CraeteObjectを使ってインスタンスを生成するように変更します.

Set objDb = CreateObject("vbpDAO.clsDAO")

 CreateObjectのパラメタは文字列定数または変数が指定できるので,実行ファイルの起動時パラメタなどで使用するクラスを指定して,再コンパイルなしにプログラムの機能を変更することができます.ただし,実行ファイルをパラメタ付きで起動するためには,[スタート]/[ファイル名を指定して実行]メニューからプログラムを起動するか,ショートカットで定義するか,DOSプロンプトから起動するかの方法をとる必要があります.

SQL Server対応版を作成する
 共通機能部分はそのままで,ActiveX DLL部分を変更します.まず,参照設定を[Microsoft DAO 3.5 Object Library]から[Microsoft Remote Data Object 2.0]に切り替えます.そして,機能のインターフェイスは変更せずに内部処理をRDO用に変更します(リスト6).また,MDBファイルの選択画面をODBCデータソースのログオン画面に変更します.


Oracle対応版を作成する
 共通機能部分はそのままで,ActiveX DLL部分を変更します.まず,参照設定を[Microsoft Remote Data Object 2.0]から[OracleInProcServer2.2 Type Library]に切り替えます.そして,機能のインターフェイスは変更せずに内部処理をoo4o用に変更します(リスト7).また,ODBCデータソースのログオン画面をオラクル用のログオン画面に変更します.


COMを使う局面
マルチDB対応アプリの作成(その2)

 このように対象となるDBのネイティブインターフェイスをラッピングすることで,ミドルウェアの相性問題を回避することが可能です.しかし,インターフェイスを同一にしたとしても,SQL文がRDBMSにより異なることもあります.
 そこで,COMを使って提供する機能レベルをもう少し高機能にして,

 (1) DBと接続する
 (2) 顧客一覧を取得する
 (3) DBと切り離す

のようにして,SQL文すらもラッピングしてしまう方法が考えられます.つまり,ビジネスロジックのオブジェクト化です.
COMを使う局面
ActiveX EXEの活用

 ActiveX EXEではActiveX DLLと異なり,呼び出し元とは別プロセスで動作します.そのため,どのようにプロセスを別にするかを決定するインスタンシングの指定が可能です.

SingleUseインスタンシング
 ActiveX EXEが呼び出されると,同じActiveX EXEが起動中でも,別個のプロセスとして起動されます.メモリなどのリソースを消費する代わりに,同じActiveX EXEを呼び出している他の実行ファイルの影響を受けることはありません.

MultiUseインスタンシング
図9:スレッドモデルの指定

 MultiUseは,[プロジェクト]-[プロパティ]のスレッドモデルの指定(図9)によりパブリック変数の扱いや他の実行ファイルの影響を受けるかどうかが決まります.

(1)  オブジェクトごとのスレッド
 ActiveX EXEが呼び出されるとたとえ同じものが起動中でも,別個のプロセスとして起動されます.SingleUseとほぼ同じ状態ですが,
(2) スレッドプール1スレッド
ActiveX EXEが起動済みであるときは,そのプロセスの同一スレッドが割り当てられます.そのため,標準モジュールに記述されたパブリック変数が複数の実行ファイル間で共通利用されます.他実行ファイルの利用状況の影響は受けますが,このことを利用すると実行ファイル間の情報共有が可能です.
(3) スレッドプールnスレッド
ActiveX EXEが起動済みであっても,そのプロセスの別スレッドとして起動されます.ただし,最大nスレッドまで起動済みであったときは,使用中ののスレッドが割り当てられます.1スレッドのときに比べて,n個の処理までは同時に処理できるので,リソースさえ十分ならば性能向上が望めます.リソース使用量の上限が決められた「オブジェクトごとのスレッド」モードと言えますが,パブリック変数が共通利用されるときを考慮して「スレッドプール1スレッド」で十分なテストを行なっておく必要があります.
図10:MultiUseサンプル画面
図11:DBコネクションプーリング

 ActiveX EXEのサンプルプログラム(Multi.exe)のスレッドモデルを変更してコンパイルし,呼び出し元の実行ファイル(MultiUse.exe)を複数起動することで,パブリック変数の使われ方がご理解いただけると思います(図10).[CreateObject]ボタンによりActiveX EXEを呼び出して,[Count Get]ボタンでパブリック変数の取得,[CountUp]ボタンで変更を行ないます.

DBコネクションプーリング
 大規模な開発を行なっていると機能ごとに実行ファイルをわける必要に出会うときがあります.このとき,複数の実行ファイル間でDBとの接続情報をどのように受け渡していくが,システム全体の使い勝手を左右します.

(1)
一番単純な方法は,実行ファイルの起動時パラメタとしてユーザーIDとパスワードを指定する方法です.この方法ならば,確かに接続時間はかかるかもしれませんが,その後は直接ミドルウェアを使うことができるので処理速度の低下はありません.また,設計・実装も簡単です.
(2)
接続時間の短縮を目指すならば,MultiUse1スレッドのActiveX EXEを経由してミドルウェアを使う方法があります(図11,リスト8・9).この方法は,ミドルウェアの機能と対応した機能をActiveX.EXEに持たせればよいので,設計段階で戸惑うことはないでしょう.しかし,マルチDB対応アプリケーションの作成のところで触れたように,COMを使うオーバーヘッドが無視できないかもしれません.
(3)
COMを使うオーバーヘッドを相殺するためには,やはりビジネスロジックをActiveX EXEに実装するのがよいでしょう.ただし,ビジネスロジックのどの部分を実装するかなどの設計を慎重に行なう必要があることと,処理時間が長時間になるようなビジネスロジックについては,呼び出し元で別コネクションを張るなどの対策が必要です.




DCOMを使わない方法
  

 DCOMの問題点は,インストールが煩雑な点とセキュリティの設定が難しい点です.そして,NT4.0が前提となっているテクノロジーなので,DCOMのエラーがイベントログとして出力されることを考えると,Windows 95では,DCOMサーバーとして使うことは論外としても,DCOMクライアントとしても使用を控えた方がよいでしょう. VBRファイルは,サーバーコンポーネントのインストールではなく,クライアントコンポントのインストールに使用されます.

図12:UDP/IP3階層システム

セキュリティ必要ですか?
 今回の特集では,DBを使うという観点からCOM/DCOMを評価しています.そこで,DBを使うことを前提としたときに,DCOMが提供しているセキュリティが本当に必要でしょうか. ユーザー認証については,DBのユーザー認証を使えば済みますし,LAN上を流れるデータの暗号化についても必要になることは少なく,もし必要ならば,市販の暗号化ライブラリを入手してもよいでしょう.DCOMのセキュリティ機能は確かに強固ですが,その裏返しとして,設定の難しさや運用時の不安定さが存在しています.強固なセキュリティが必要なシステムならば,そのような負の面をカバーしてでも構築する意味はあるかもしれませんが,そうでないときは,もっと構築しやすい方法を模索してみるのもいいと思います. たとえば,本誌97年12月号の特集で紹介したUDP/IP3階層システムなどもそのひとつの解決案になると思います(図12,リスト10).


DCOMを使う局面
DBコネクションプーリング

 運用を考えたとき,DCOMはやはりCOMに比べて扱いにくいものです.そこで,COMで接続していたDBコネクションプーリングをDCOMにより接続するための手順を追ってみることで,DCOMを使うときの注意点を探ってみたいと思います.

DCOMサーバーコンポーネントのセットアップディスク作成


 VBRファイルは,サーバーコンポーネントのインストールではなく,クライアントコンポーネントのインストールに使用されます.

 [プロジェクト]-[プロパティ]の[全般]タグの[マルチタスク]チェックボックスをチェックするとMSGBOXなどの出力先がイベントログに自動的に切り替わります.
図13:リモートサーバーファイルの指定
図14:セットアップウィザード(サーバー)

図15:ActiveXコンポーネント(サーバー)
図16:共有ActiveXアプリケーション(サーバー)

図17:セットアップウィザードの実行
図18:分散COMの構成(クライアント)

開発環境からDCOMサーバーコンポーネントへの接続設定

(1)
dcomcnfg.exeを起動して,アプリケーションの配置を切り替えます(図18)
(2)
現在の配置は,[全般]タグに表示されます.ローカルパス及びリモートコンピュータを確認します(図19)
 このことは,リモートコンピュータを切り替えたときは,設定を変更しなければならないことを意味しています.前述のUDP/IP3階層システムは,同一サブネット内ならば,勝手にサーバーを検出することも可能です.DCOMもUDP/IPを利用しているのですから,このようなこともサポートして欲しいですね.

(3)
もし,リモートコンピュータ名に相違があれば[場所]タグで指定します.確実にリモート側で動作させたいときは,[次のコンピュータ上でアプリケーションを実行する]チェックボックスのみチェックしてください.
 コンピュータ名の指定欄ですが,NT版のdcomcnfgには,ToolTipsの表示通りに[参照]ボタンが存在しますが,Win95 OSR2.5版には存在しません(図20).

図19:分散COMのプロパティ(クライアント)
図20:サーバーコンピュータの指定(クライアント)


DCOMサーバーコンポーネントの起動

(1)
DCOMを使うとリモートコンピュータ上で自動的にDCOMサーバーコンポーネントが起動されます(図21).
(2)
[マルチタスク]チェックボックスがチェックされていれば,エラーはイベントログとして出力されます(図22).

図21:サーバー側でのタスクの起動
図22:サーバー側のイベントログ


DCOMクライアントコンポーネントのセットアップディスク作成

(1)
セットアップウィザードでプロジェクトファイルを指定すると,そこで使われているDCOMサーバーコンポーネントが表示されます(図23)
(2)
ここで,忘れずに[リモートコンポーネントの追加]を行ないます(図24).これは,dcomcnfgでの設定内容を同じものなので,配布後dcomcnfgで修正することも可能です


図23:セットアップウィザード(クライアント)
図24:ActiveXコンポーネント(クライアント)


 以上の手順により,大抵は正常に動作しますが,セットアップ後,ユーザーが所属するセキュリティグループを切り替えたときなどには,必ず動作確認テストを行なうほうがよいでしょう.DCOMのセキュリティは,NTドメインのセキュリティと密接な関係があるので,総合的なセキュリティ方針の設計が重要になります.行き当たりばったり的な「動いたからOKOK.参照できなくなったからOKOK」というようなセキュリティの設定をしているとさっきまで動作していたDCOMコンポーネントが動作しなくなる危険性を含んでいます.

[動作確認]
Panasonic CF-S21
 Windows 95 4.00.950 C
  IE4.0 4.72.2106.9(non ActiveDesktop)
  Visual Basic 5.0 (SP3)
  Oracle Objects for OLE 2.2.3
Pentium MMX200Mhz 128MB
 Windwos NT 4.0 Server (SP3)
  Oracle8 Enterprise Edition R8.0.4

サンプルプログラムのダウンロード


VB Magazine ライブラリ | Visual Basic WorkGroup
int21 ホームページ | PCDN ホームページ


Copyright (c) 1998 int21 Corporation All Rights Reserved.
For questions or comments, please send mail to: pcdn@int21.co.jp