WebClassアプリケーションは,Active Server Pagesアプリケーションである

VBユーザーならWebClassなんて怖くない!?

著/秋月 巌 AKIZUKI, Iwao


標準的なCGIアプリケーションの開発に不向きなVisual Basic

    この2年間でVisual Basicを使用してWebアプリケーションを開発するための環境は,十分に完備されたといっていい.それまで,Webアプリケーションを記述するためのCGIといえば,PerlスクリプトやC言語で記述されるのが一般的だった.
 Visual BasicがCGIを記述するのに不向きだったのは,当時のWebサーバーのほとんどがUNIXであったということに加えて,Visual Basicが標準入出力をサポートしていなかったためである.そのため,Windows NTをWebサーバーとして利用しているユーザーも,単純な方法ではVisual BasicでWebアプリケーションを開発することはできなかった.Webアプリケーションからのデータを,最終的にブラウザに返信するためWebサーバーを利用する.そのために作成したアプリケーションとWebサーバーが連携をとる必要があり,その仕組みに標準入出力を使用するのが標準的なCGIプログラミングだったのである.

制限を越えるために…

    この制限をクリアするため,米国では,入出力の内容を一度テンポラリーファイルに出力し,それを再度,アプリケーションで読み書きすることで,Webサーバーと連携する方法が一時普及した.有償無償を問わず,そのためのモジュールが公開されたのが,2年ほど前である.私自身も本誌で,この仕組みを用いたモジュールを紹介したことがあるが,日本ではあまり普及しなかったようである.当時,まだ日本ではWebはスタティックなページであることが当たり前であり,Webアプリケーションの需要も小さかったからである.

IIS1.0の登場

    それまで,Windows NT用のWebサーバーはサードパーティから発売されていたのだが,MicrosoftはInternet Information Server1.0(IIS1.0)の提供を開始する.このWebサーバーにはInternet Database Connector(IDC)と呼ばれるデータベースへのゲートウェイが用意されていた.IDCはデータベース専用の接続を提供するメカニズムだったが,Microsoft SQL Serverのような拡張されたSQL言語をサポートするデータベースサーバーを使用することで,必ずしもデータベースにアクセスしなくても,CGIプログラミングを実現することができた.しかし,この方法はストアドプロシージャを使用してプログラミングを行なうため,Jetデータベースエンジンのように構造化されたストアドプロシージャを作成できないデータベースエンジンを使用する場合には,プログラミングの範囲は極端に限定された.
 また,Visual Basicでアプリケーションを記述するためには,OLEオートメーションストアドプロシージャを使い,COMコンポーネントを呼び出す必要があった.しかし,当時のVisual Basic 4.0はマルチスレッド対応のコンポーネントが作成できなかったのだから,現実的な選択肢ではなかった.

幻となったOLEISAPI

    そのころ,OLEISAPIと呼ばれるモジュールが一部のVisual Basicプログラマに利用されたことがある.本誌でもW.Stealride氏が記事を掲載したことがあるので,ご存知の方もいるだろう.ISAPIはIISが提供するプログラミングインターフェイスだが,これを利用するには標準DLLを作成する必要がある.Visual BasicはActiveX DLLの作成は可能だが,標準DLLを作成できない.この制約をクリアするために用意されたのが,OLEISAPIである.OLEISAPIモジュール自体は,標準DLLとして実装されており,ActiveX DLLとのブリッジ役を果たす.Visual BasicデベロッパはActiveX DLLを作成すれば,OLEISAPIモジュール経由でISAPIインターフェイスを使用することができる.
 OLEISAPIはMicrosoftが公開したモジュールでActiveX SDKに収録されていたが,正式にリリースされたものではなく,また,致命的なバグがあることで有名だった.ただ,OLEISAPIモジュールのソースコードが公開されていたため,モジュールのバグフィックスを独自に行なって使用していた開発者もいたようである.

主役となったActive Server Pages

    当時,私はVisual BasicによるWebプログラミングはOLEISAPIによる実装が標準になると信じていたが,OLEISAPIは正式のモジュールがリリースされることもなく,ActiveX SDKから取り外された.その最大の原因はDenaliと呼ばれる新しいメカニズムの登場である.Denaliは後にActive Server Pagesと改名され,Windowsの標準的なWebアプリケーション開発メソッドとして定着する.
 Active Server Pagesは基本的には,言語非依存のゲートウェイメカニズムである.Active Server PagesのプログラミングにVBSを使用するのは,Active Server PagesがVBSの言語エンジンを利用するからであり,決してActive Server PagesがVBSに特化しているからではない.そして,MicrosoftのJava ScriptであるJscriptの言語エンジンもActive Server Pagesと同時にインストールされることを考えれば,Active Server Pagesが複数の言語をサポートするということは明確である.
 Active Server Pagesがその拡張性という意味で優れているのは,対応言語についてだけではない.サーバー側でのCOM呼び出しをサポートしたことで,Active Server PagesはMicrosoftのWebメカニズムとして主役の座を与えられたのである.

WebClassとActive Server Pages

    今回,紹介するWebClassも動作の仕組みとしては,Active Server PagesのCOMサポートを利用している.WebClassの利点といえば,Visual Basicの知識だけでWebアプリケーションの構築が可能ということが筆頭にあげられる.しかし,Visual Basicで作成するのは,あくまでもCOM(ActiveX)コンポーネントだけであり,Active Server Pagesを記述する必要はない.
 もっとも,Visual Basicの知識だけでWebアプリケーションの開発が可能だという言葉の意味は,Visual Basic 6.0の知識だけで開発が可能だということであり,決してVisual Basic 5.0の知識だけで開発できるという意味ではない.Visual Basic 5.0のユーザーにとっては,WebClassの混乱したアーキテクチャよりは,Active Server Pagesの知識を追加する方がよっぽど簡単であり,最終的に利用範囲は広がるだろう.
 WebClassのActive Server Pagesに対するメリットとして,ほかにも実行速度の差やソースコードの隠蔽性もあげることができる.しかし,これらのメリットもActive Server Pagesに加えて,Visual Basic5.0(もちろん,Visual Basic 6.0でもいい)で作成したCOMコンポーネントを利用すれば,まったく同等の特徴を得ることができる.
 つまり,WebClassと,Active Server Pages + COMコンポーネントは,まったく同じ目的と能力をもっているということができる.動作のメカニズムとしてWebClassがActive Server PagesのCOMサポートを利用していることを考えれば,これは当然の結果である.

WebClassの優位点

    最終的にWebClassの優位点として上げられるのは,デバッガの完成度かもしれない.Active Server PagesもVisual InterDev 6.0を使用することで,すばらしいデバッグ環境を手にすることができる.しかし,残念なことにVisual InterDevのデバッガの動作は,私のマシン上では不安定であり,個人的にはWebClassで使用するVisual Basicのデバッガの方が信頼できる.
 もっとも,デバッグ環境の充実をどの程度重要視するかは,開発者の個人差が大きいだろう.Active Server PageはMicrosoft Script Debugerが発表されるまで,デバッグ環境が存在していなかった.私は数多くのActive Server Pagesアプリケーションをデバッガを使うことなくテキストエディタで開発してきたが,不便を感じたことはなかった.もっとも,もし,その時点で優秀なデバッガが存在していれば,私は5%くらいは短い時間でアプリケーションの開発を終了していたかもしれない.
 結局のところ,Active Server Pagesを用いるか,WebClassを用いるかは内部的な動作が同じである以上,開発者の好みの問題でしかない.Active Server Pagesおよび,そのCOMサポートはMicrosoftの最近の技術の中でも,特に安定している.WebClassのアーキテクチャが混乱しているといっても,それはコンセプトが混乱しているだけであって,動作メカニズムが混乱しているわけではない.つまり,WebClassのプログラミング方法は理解しにくいが,一度理解してしまえば決して複雑ではないし,動作そのものはActive Server Pagesと同程度に安定すると思われる.

同じサンプルを3つの方法で実装

    本稿では,同じアプリケーションを次の3つの方法で実装することで,それぞれのプログラミングの違いを説明する.
  • ケース1:Active Server Pagesのみ
  • ケース2:Active Server Pages + COMコンポーネント
  • ケース3:WebClass
 作成するアプリケーションは2つのページ(図1)から構成される簡単なものである.最初のページに表示される2つのテキストボックスに数値を入力して「送信」ボタンをクリックすると,次のページには入力した値の合計値が表示される.
   数字を入力してください 2と4を入力
↓値を入力してクリック
入力した値の合計は6です
図1計算値入力ページと計算結果表示ページ
    Active Server Pagesでは,VBSのユーザー定義関数を使って計算処理を実装し,Active Server Pages + COMコンポーネントでは,Visual Basicで作成したActiveX.DLLに計算処理を行なうための関数を格納する.WebClassのケースでは,ケース2と同様,ActiveX DLLとして実装されるがVisual Basicで開発する段階では,WebClassとして扱われる.

ケース1:Active Server Pagesのみを使った実装

    リスト1,2はActive Server Pagesを使用してサンプルプログラムを実装した場合の全ソースコードである.リスト1は<INPUT>タグを使って2つのテキストボックスとサブミットボタンを表示したHTMLファイルだ.入力された値を送信するページとしてASPsample.aspが指定されている.
 このページで入力された値はサブミットボタンのクリック時に,tex1とtext2という名前でASPsample.aspに渡される.このHTMLコードは,ケース2,3でも利用される.
 リスト2は実際の計算処理を行なうASPファイルである.コードの冒頭でユーザー定義関数であるCalc関数が指定されている.この関数は2つの引数を受け取り,その合計値を戻り値として呼び出し元に返す.定義の方法はVisual Basicと変わらない.
 この関数を使用しているのは,次の部分である.
      recText1 = Request.Form("text1")
recText2 = Request.Form("text2")
Response.Write(calc(recText1,recText2))
    RequestオブジェクトのFormプロパティは,このページを呼び出した元のページによって送信された内容を取得する.引数にtext1が指定されていれば,text1テキストボックスが保持していた値を受け取ることができる.この値は変数recText1に格納され,Calc関数の引数として利用される.
 ResponseオブジェクトのWrite関数は,引数に指定された内容をページに出力する.この場合は引数にCalc関数が指定されているので,計算結果がページに出力されることになる.
 RequestオブジェクトとResponseオブジェクトはActive Server Pagesでプログラミングをする場合に,不可欠なオブジェクトであると同時に,WebClassでも利用される.
 このケースでは,"Calc関数をビジネスロジックとして利用している"ということができる.この関数の内容を修正することで,たとえば消費税計算プログラムや保険金計算プログラムに変更することができる.
リスト1:計算値入力ページ(ASPsample1.htm)
       <HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type"
    Content="text/html; charset=x-sjis">
</HEAD>
 <BODY>
  <FORM action=ASPsample2.asp method=POST>
  数字を入力してください<BR>
   <INPUT type="text" name=text1>
   <INPUT type="text" name=text2>
   <INPUT type="submit" value="送信">
  </FORM>
</BODY>
</HTML>

リスト2:結果表示ページ(ASPsample2.asp)
       <%@ Language=VBScript %>
 <%Function Calc(param1,param2)
    Calc = int(param1) + int(param2)
   End Function%>

<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type"
   Content="text/html; charset=x-sjis">
</HEAD>
 <BODY>
 <%
  recText1 = Request.Form("text1")
  recText2 = Request.Form("text2")
  Response.Write(calc(recText1,recText2))
 %>

 </FONT>です.
 </BODY>
</HTML>

ケース2:Active Server Pages + COMコンポーネントを使った実装

    このビジネスロジックをCOMコンポーネントに実装したのが,リスト3,4,5のActive Server Pages + COMコンポーネントバージョンである.
 リスト3はVisual Basicで作成されたActiveXコンポーネントに記述されたCalcメソッドである.このプロジェクトの名称はAxcomであり,Calcメソッドが記述されているClass名前はClass1である.このコンポーネントには,リスト3以外のコードは一切記述されていない.
 リスト4は計算入力ページである.<FORM>タグのactionオプションがAxsample2.aspと指定されていることを除けば,ケース1のActive Server Pagesバージョンのものと変わらない.
 リスト5の次のコードで,Visual Basicで作成したAxcomプロジェクトのClass1クラスのインスタンスを作成している.
       set CalcOBJ = CreateObject("AXcom.class1")
    オブジェクトのポインタはCalcOBJオブジェクト変数に格納される.
 以下のコードでコンポーネント内のメソッドを利用し,計算した結果をページに出力している.
       result = CalcOBJ.Calc (recText1,recText2)
Response.Write (result)
    計算はCalcメソッド(リスト3)に記述した内容にしたがって行なわれる.Active Server Pagesを使ったケース1ではVBSの関数として実装されていたものが,ここではVisual Basicの関数として定義されている.このケースのような単純な計算では差が出ないが,複雑な計算処理を行なった場合はVBSとVisual Basicの実行速度の差が処理時間に現われてくるだろう.もっともActioveX DLLを使った場合,コンポーネントのインスタンス化に時間がかかるので,軽量な処理の場合はActive Server PagesのVBSで記述した方が処理は高速になる.
リスト3:Visual BasicのAXcomプロジェクトのClass1クラスに記述されたCalcメソッド
       Public Function Calc(param1, param2) As Variant
  Calc = Int(param1) + Int(param2)
End Function
リスト4:計算値入力ページ(AXsample1.htm)
       <HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type"
   Content="text/html; charset=x-sjis">
</HEAD>
 <BODY>
  <FORM action=AXsample2.asp method=POST>
  数値を入力してください.<BR>
   <INPUT type="text" name=text1>
   <INPUT type="text" name=text2>
   <INPUT type="submit" value="送信">
  </FORM>
 </BODY>
</HTML>
リスト5:結果表示ページ(AXsample2.asp)
       <%@ Language=VBScript %>
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type"
   Content="text/html; charset=x-sjis">
</HEAD>
 <BODY>
  入力した値の合計は<FONT SIZE=5>
  <%
   set CalcOBJ = CreateObject("AXcom.class1")
   recText1 = Request.Form("text1")
   recText2 = Request.Form("text2")
   result = CalcOBJ.Calc (recText1,recText2)
   Response.Write (result)
  %>

  </FONT>です.
 </BODY>
</HTML>

ケース3:WebClassを使った実装

    WebClassを作成するには,新規プロジェクトを作成する際にIISアプリケーションを選択する(図2).空のプロジェクトが開いたら,プロジェクト名をWebClsに変更する.
 プロジェクトエクスプローラからWebClass1を選択し(図3)ダブルクリックすると,WebClassデザイナが起動する(図4).
 WebClassデザイナを使用してHTMLテンプレート(WebTemplate1)とカスタムWeb項目(WebItem1)を追加する.HTMLテンプレートに使用するテンプレートはWCsample1.htm(リスト6)を利用する.
 右クリックメニューを使用して「WebItem1」カスタムWeb項目に「FormSubmit1」ユーザー定義イベントを追加する.
 テンプレートに使用したWCsample1.htm(リスト1)は,<FORM>タグのactionオプションが変更されていることを除けば,前出の計算値入力ページと同じである.actionオプションに指定されているWebClass1.ASP(リスト7)は,Visual BasicがIISアプリケーションのコンパイル時に生成したASPファイルである.このプロジェクトで作成したWebアプリケーションを実行する場合,Webブラウザで指定するURLは,常にこのファイルを指定することになる.アプリケーションが複数のページによって構成されている場合は,引数によってページが特定される.アプリケーションの開発中,このASPファイルが変更されることはない.
 テンプレートファイルは本来,途中にタグを埋め込むことで動的にページを生成する補助として使用するのだが,ここでは静的なページ表示のために利用する.
   IISアプリケーションを選択
図2:新しいプロジェクトを作成する際にIISアプリケーションを選択

WebClass1を選択
図3:WebClass1を選択

Webデザイナ
図4:Webデザイナ
リスト6:テンプレートに利用した計算値入力ページ
       <HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type"
   Content="text/html; charset=x-sjis">
</HEAD>
 <BODY>
  <FORM action= WebClass1.ASP?WCI=WebItem1&WCE=FormSubmit1 method=post>
   数値を入力してください.<BR>
   <INPUT name=text1 >
   <INPUT name=text2 >
   <INPUT type="submit" value="送信">
  </FORM>
 </BODY>
</HTML>
リスト7:Visual Basic 6.0が生成したASPスクリプト(VBS)
       <%
Server.ScriptTimeout=600
Response.Buffer=True
Response.Expires=0

If (VarType(Application("~WC~WebClassManager")) = 0) Then
 Application.Lock
 If (VarType(Application("~WC~WebClassManager")) = 0) Then
   Set Application("~WC~WebClassManager&qout) = _
   Server.CreateObject("WebClassRuntime.WebClassManager")
 End If
 Application.UnLock
End If

Application("~WC~WebClassManager&qout).ProcessNoStateWebClass _
 "WebCls.WebClass1", _
 Server, _
 Application, _
 Session, _
 Request, _
 Response
%>
    リスト8は,WebClsプロジェクトに記述されたソースコードである.
 たとえば次のようなURLによってIISアプリケーションの実行が指定された場合,WebClassのStartイベントプロシージャが実行される.
       http://マシン名/WebClass1.ASP
    このサンプルでは,次のコードが実行されることになる.
       Private Sub WebClass_Start()
 Set NextItem = WebTemplate1
End Sub
    このコードは「WebTemplate1」Web項目を実行することを意味する.Web項目が実行される場合,デフォルトではRespondイベントが発生し,それに関連付けられた次のプロシージャが実行される
       Private Sub WebTemplate1_Respond()
 WebTemplate1.WriteTemplate
End Sub
    このプロシージャでは,テンプレートに指定されているファイルの内容を,ページに出力することが指定されている.テンプレートに指定されているのはリスト6の計算値入力ページだから,その内容がWebページに表示される(図1).
 オペレータが,計算値入力ページに値を入力し「送信」ボタンをクリックすると,<FORM>タグのactionオプションの記述にしたがって,再びWebClass1.ASPが呼び出される.しかし,今度は次のような引数が指定されていることに注意してほしい.
       WCI=WebItem1&WCE=FormSubmit1
    この引数は「WebItem1」Web項目のFormSubmit1イベントを引き起こすことを指示している.このイベントによって実行されるのは,WebItem1_FormSubmit1プロシージャである.イベントによってイベントプロシージャが呼び出されるという形になってはいるが,呼び出されるプロシージャが引数によって指定されているだけだと考えた方がわかりやすい.
 このアーキテクチャを考案した人間はイベントという言葉を利用した方がWebClassが高級に見えると考えたようだが,実際にはWebClassの概念をわかりにくくしただけである. 「WebItem1」Web項目のWebItem1_FormSubmit1プロシージャでは以下のように静的なHTMLコードを出力し,そして計算結果を動的に出力する.計算のために用いられたCalc関数は,Visual Basicのユーザー定義関数として定義されている.
 静的なHTMLコードをページに出力するのに,このようにコードに埋め込むのではなく,HTMLテンプレートを使用することも可能だ.テンプレートを利用すれば,引用符で囲む必要はなくなるが,残念ながらVisual Basic 6.0のテンプレート編集機能は,私のコンピュータでは動作しない.
       With Response
  .Write "<HTML>"
  .Write "<HEAD>"
  .Write "<META HTTP-EQUIV=""Content-Type" _
   " Content=""text/html; charset=x-sjis"">"
  .Write "</HEAD>"
  .Write "<BODY>"
  .Write "入力した値の合計は <FONT SIZE=5>"
  .Write (Calc(recText1, recText2))

リスト8:WebClsプロジェクトの全ソースコード
       Private Sub WebClass_Start()
 Set NextItem = WebTemplate1
End Sub

Private Sub WebTemplate1_Respond()
 WebTemplate1.WriteTemplate
End Sub
Function Calc(param1, param2)
 Calc = Int(param1) + Int(param2)
End Function
Private Sub WebItem1_FormSubmit1()
 Dim recText1, recText2
 recText1 = Request.Form("text1")
 recText2 = Request.Form("text2")
 With Response
  .Write "<HTML>"
  .Write "<HEAD>"
  .Write "<META HTTP-EQUIV=""Content-Type" _
   " Content=""text/html; charset=x-sjis"">"
  .Write "</HEAD>"
  .Write "<BODY>"
  .Write "入力した値の合計は <FONT SIZE=5>"
  .Write (Calc(recText1, recText2))
  .Write "</FONT>>です."
  .Write "</BODY>"
  .Write "</HTML>"
 End With
End Sub

理解しにくいのは,命名に問題

    今回,Visual Studio 6.0の評価を通して,いくつかの機能が私のコンピュータでは動作しないことを確認した.使用しているコンピュータは評価用の比較的コンディションのよいマシンである.それでもきっと,他のコンピュータでは正常に動作するのだろう.もっとも,誰もWindows上で完璧に動作するアプリケーションなど作成することはできないのだから,私はVisual Studio 6.0が他社の開発ツールと比較して特に品質が悪いとは考えていない.
 本稿を読んで,WebClassの全体像が理解できなかったとしても,私のことを責めないでほしい.WebClassはわかりやすい技術を,わかりにくい名称で名づけなおした特殊な存在である.
 WebClassではたいていの場合,ひとつのプロシージャによって,ひとつのWebアプリケーションのページを生成する.Web項目とは,それらのプロシージャが収められているライブラリである.このサンプルでは,2つのWeb項目にコードを格納したが,これをひとつのWeb項目に収めなおすこともできる.つまり,Web項目とは,複数のプロシージャを収納するためのモジュールだということができるのだ.フォームモジュールやクラスモジュールと同様である.こういうものに,なぜ「…項目」という名称が与えられたのか,私にはよくわからない.私だったら,Webモジュールという名称にしただろう.

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


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