連載:熱血VBプログラマ応援団


第6回 XML Webサービスに待ち構える暗黒面(後編)

―― VB.NETで軽やかに乗り越えて光を目指せ! ――

株式会社ピーデー 川俣 晶
2004/06/09
 

前回のご相談の概要 −

 XML Webサービスは何でも実現できる夢のような技術に思えますが本当でしょうか?それを活用するには、WebアプリケーションやXMLの知識が必要なのでしょうか? また、XML Webサービスが使えないと、スマート・クライアントも開発できないのでしょうか?

 前回はVisual Basic .NET(以降、VB.NET)によるXML Webサービスの作成に触れた後、XML Webサービスの持つ暗黒面の1つ、呼び出しに時間がかかるという問題についてお話ししました。前回冒頭で述べたように、悪い話の次は良い話です。

良い話:別の手段その1 REST

 XML Webサービスの暗黒面に嫌気がさしている人たちは、何年も前からいました。そして、彼らから提唱されたXML Webサービスの対抗技術ともいえるものがあります。これはREST(REpresentational State Transfer)と呼ばれますが、具体的な技術仕様ではなく、既存技術を使って、もっと軽くシンプルにXML Webサービスと同じことが実現できるじゃないか、という趣旨のものです。

 当然、XML Webサービスを推進するマイクロソフトは、対抗技術であるRESTなど認めてはいません。その結果として、VB.NETには、特にRESTをサポートする機能は含まれていません。

 しかし、そこで断念するのは気が早いのです。VB.NETからは.NET Frameworkの膨大なクラス・ライブラリを利用することができます。その中には、RESTが前提とするさまざまな既存技術を扱うためのクラスが用意されています。それらのクラスは、Webアプリケーションや、XML Webサービスを実現するためにも必要とされるため、用意されて当たり前なのです。

 では、RESTによって、前回のサンプル・コードと同じことを実現してみましょう。メソッドを公開するサーバ・プログラムと、それを呼び出すクライアント・プログラムです。

 まずサーバ側です。Webアプリケーションとしてプロジェクトを作成してASP.NETで動作しますが、HTMLなどは使っておらず、いわゆるWebアプリケーションではありません。

Imports System.Xml

Public Class WebForm1
  Inherits System.Web.UI.Page

……Web フォーム デザイナで生成されたコード……

  Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Response.ContentType = "application/xml"
    Response.ContentEncoding = System.Text.Encoding.UTF8

    Dim writer As XmlTextWriter = New XmlTextWriter(Response.OutputStream, System.Text.Encoding.UTF8)
    Try
      writer.WriteStartDocument()
      writer.Formatting = Formatting.Indented
      writer.WriteElementString("result", Val(Request("price")) * 80 / 100)
      writer.WriteEndDocument()
    Finally
      writer.Flush()
    End Try
  End Sub

End Class

 クライアント側は、これが最善か分かりませんが、こんな感じでさらさらっと書いてみました。コンソール・アプリケーションとして書いてあります。

Imports System.IO
Imports System.Net
Imports System.Web
Imports System.Xml

Module Module1

  Function SampleQuery(ByVal price As Integer) As Integer
    Dim client As WebClient = New WebClient
    client.Headers.Add("user-agent", "SampleProgram")
    client.Headers.Add("Content-Type", "application/x-www-form-urlencoded")

    Dim requestArray() As Byte = System.Text.Encoding.UTF8.GetBytes("price=" & price.ToString())
    Dim resultArray() As Byte = client.UploadData("http://localhost/SampleRestSvc001/WebForm1.aspx", "POST", requestArray)

    Dim resultDocument As New XmlDocument
    resultDocument.Load(New MemoryStream(resultArray))

    Return Val(resultDocument.InnerText)
  End Function

  Sub Main()
    Dim sum As Integer
    Dim startTime As DateTime = DateTime.Now
    For i As Integer = 0 To 10000
      sum += SampleQuery(i)
    Next
    Dim endTime As DateTime = DateTime.Now
    Console.WriteLine(sum)
    Console.WriteLine(endTime.Subtract(startTime))
  End Sub

End Module

 このコードを見ると、XML Webサービスを使った場合と比較して、かなりコード量が増えていることが分かります。これは低レベルの機能を組み合わせて実現しているためです。また、HTTPというプロトコルや、URI(URL)の書式についてある程度知らないとコードが書けないというハードルの高さもあります。明らかに、XML Webサービスと比較して、楽ではない世界といえます。

 しかし、メリットがないわけではありません。これを筆者のPCで実行すると、以下のような処理時間となりました。

REST版
00:00:48.4906932

 前回でXML Webサービスを使った版が約1分39秒だったことを考えると、約半分の処理時間で完了していることが分かります。もちろん、別のコンピュータ上の処理を呼び出す機能性を持っていて、かつ、既存のHTTPというプロトコルを使っているので、プロキシを超えて通信することもできます。つまり、プログラムの難度が高くなり、コードが増えることを了承するのであれば、XML Webサービスよりも早い通信手段があるということです。

 さて、ここで強調しておきたいことは、VB.NETは必要とあれば、こういうプログラムを即座に組めるだけの汎用性と基礎的なクラス・ライブラリに恵まれているということです。

 VB.NETを使えば、XML Webサービスを即座に組めるというのは1つのメリットではありますが、真のVB.NETの価値は、あらかじめベンダ側から用意されたわけではない別の世界(例えばREST)にも、容易に対応できることだと思います。

良い話:別の手段その2 .NETリモート処理

 ファイアウォールを越えなくてよければ、もっと高速かつ簡単に通信する方法があります。それは.NET Frameworkのクラス・ライブラリが提供するバイナリ形式の.NETリモート処理(.NET Remoting)です。これは、独自のプロトコルでデータをやりとりすることによって、別コンピュータのメソッドを高速に呼び出すことを可能とするものです。イントラネット内だけで完結するシステムなどでは、これを使うことができるでしょう。

 簡単なサンプル・コードを作ってみましたので、以下に掲載します。詳細を理解する必要はありませんので、雰囲気をつかんでください。

 まず、別コンピュータから呼び出されるメソッドを含むクラスを、クラス・ライブラリのプロジェクトとして作っておきます。以下のような感じです。

Public Class SampleService
  Inherits System.MarshalByRefObject
  Public Function CalcPrice(ByVal basePrice As Integer) As Integer
    Return basePrice * 80 / 100
  End Function
End Class

 これを見て分かるとおり、Inherits System.MarshalByRefObjectによってSystem.MarshalByRefObjectクラスを継承しているほかは、ごく普通のクラスです。このようなクラスを作成することは手慣れたVBプログラマならいとも簡単でしょう。

 そして、サーバ側のプログラムは以下のような感じです。コンソール・アプリケーションとして作成されています。

Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp

Module Module1

  Sub Main()
    Const portNumber = 8910
    Dim chan As TcpChannel = New TcpChannel(portNumber)
    ChannelServices.RegisterChannel(chan)
    RemotingConfiguration.RegisterWellKnownServiceType(Type.GetType("SampleRemLib001.SampleService,SampleRemLib001"), SampleService", WellKnownObjectMode.Singleton)
    Console.WriteLine("リターンキーを押すと終了します。")
    Console.ReadLine()
    ChannelServices.UnregisterChannel(chan)
  End Sub

End Module

 サーバ側のプログラムで行われていることは、外部からの呼び出しを受け付けるクラス(クラス・ライブラリのプロジェクトとして作成したSampleServiceクラスです)を登録したり、TCP/IPのポート番号(ここでは8910番)を指定したりすることです。ポート番号を指定する部分にのみ、少々ネットワークの知識を必要としますが、RESTに比べればわずかなものです。

 一方、クライアント側は以下のようになります。コンソール・アプリケーションとして作成されています。

Module Module1

  Sub Main()
    Dim service As SampleRemLib001.SampleService = CType(Activator.GetObject(GetType(SampleRemLib001.SampleService), "tcp://localhost:8910/SampleService"), SampleRemLib001.SampleService)
    Dim sum As Integer
    Dim startTime As DateTime = DateTime.Now
    For i As Integer = 0 To 10000
      sum += service.CalcPrice(i)
    Next
    Dim endTime As DateTime = DateTime.Now
    Console.WriteLine(sum)
    Console.WriteLine(endTime.Subtract(startTime))
  End Sub

End Module

 Activator.GetObjectメソッドによって、別コンピュータのオブジェクトを取得する部分を除けば、何ら特別なコーディングは行われていないことが分かるでしょう。

 そして速度的な効果は絶大です。筆者のPCで実行すると以下のような結果になりました。

.NETリモート処理版
00:00:12.8287026

 XML Webサービスを使った版が約1分39秒、REST版が約48秒だったことを考えると、比較にならない高速性が発揮されていることが分かると思います。

 さて、ここで再び強調しておきたいことは、VB.NETから使用できるのは、流行の派手な機能だけではない、ということです。このような実利的な機能も用意され、容易に利用できます。

 VB.NETが、汎用性の高さと併せて、そのような機能を持っていることは、多くの技術上の選択肢をプログラマに与えてくれます。

 技術上の選択肢が多いことは、いろいろなシステム開発に対応できる可能性を広げるだけでなく、流行の変化が起こっても、VB.NETによって対応し続けられる可能性を高めます。この適応性の高さは、伝統的にBASIC言語の特徴であると思いますが、VBを使い続ける安心感にもつながると思います。

 頑張れVBプログラマ、君たちが使うVisual Basic.NETは取り組む価値のある可能性に満ちたプログラム言語だ!End of Article

インデックス・ページヘ  「熱血VBプログラマ応援団」

@IT Special

- PR -

TechTargetジャパン

Insider.NET フォーラム 新着記事
  • Python Fire (2017/3/28)
     Python FireはPythonコードに対するコマンドラインインタフェースを自動生成するライブラリ。グーグルがオープンソースプロダクトとして公開している
  • Visual Studio 2017が目指す世界とは? (2017/3/24)
     Visual Studio 2017はもはやWindowsアプリ開発者のためだけのものではない。どんなアプリを開発できるのかを見てみよう
  • foreachループで現在の繰り返し回数を使うには? (2017/3/23)
     LINQのSelect拡張メソッドを使用して、foreachループの中で現在が何回目の繰り返しなのか、そのインデックスを得る方法を紹介する(C# 7/VB 15対応)
  • Listの要素を並べ替えるには? (2017/3/22)
     LINQのOrderBy/ThenByなどの拡張メソッドとListクラスのSortメソッドを利用して、Listの要素を並べ替える方法を解説する
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

イベントカレンダー

PickUpイベント

- PR -

アクセスランキング

もっと見る

ホワイトペーパーTechTargetジャパン

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH