XML Webサービスにおける疎結合とは何か
|
|
XML Webサービスは「疎結合システム」の開発を支援する技術である。疎結合(loosely coupled)とは、システムのある部分とほかの部分とが緩やかに接続され、緩やかであるが故にいつでも取り替え可能である状態を指す。例えば大企業の出張申請を想像してほしい。社員が出張のたびに航空券を旅行会社に買いに行くのは面倒だ(Web購入ができるようになったのはつい最近であることを思い出してほしい)。そこで、事務の担当者が出張申請を受けて、「いつもどおりの」航空会社からボリューム・ディスカウントのチケットを購入し、それを出張に行く社員に渡していたはずだ。航空会社は激烈な競争を繰り広げているから、企業によっては条件が良ければ航空会社を変えてしまうこともあった。だが、出張に行く社員にはそんなことは関係ない。同じ担当者からチケットを受け取って、指定された時間に空港に行くだけだ。
大企業が、ときには利用する航空会社を変更できたのはなぜか。それは、航空会社がどこも同じようなインターフェイス(営業マン、企業専用受付電話など)を持っているからだ。航空会社を変えても、担当者の作業は大して変わらない。せいぜい電話番号が変わる程度だ。このように、共通のインターフェイスにのっとることで、やりとりの相手を柔軟に変更できるようにする、それが疎結合の考え方だ。
それでは、XML Webサービスの技術を使えば、疎結合は何もせずに手に入るのだろうか。結論をいえば、そんなことはない。XML Webサービスの解説を読むと、「システムがXMLで結ばれることで、疎結合が実現できる」というフレーズに必ずお目にかかるが、このような認識はナイーブすぎることにそろそろ気付かなければならない。XMLを使ったからといって、疎結合が実現できるわけではないのだ。
コンピュータ同士が接続し合うXML Webサービスの世界では、上記の航空会社の例のような大まかなインターフェイス(電話をかけて、「何月何日どこからどこまで1名禁煙通路側」というせりふをいう)では駄目なことは明白だろう。コンピュータは頭が固い。もっと細かいインターフェイスの定義が必要だ。疎結合を実現するには、前回のオピニオンでも解説したとおり、インターフェイスを堅牢にすることが不可欠となる。インターフェイスを堅くするとは、つまり厳しい型付けを行うということだ。型付けは厳しく、結合は緩やかに(疎に)する、それがXML Webサービスの成功の鍵だ。
型付けを厳しく(strongly typed)するために、XML WebサービスではXML Schemaを利用してメッセージの型を定義する。メッセージの型とは、必ずしもintやstringのようなデータ型ではない。XML WebサービスはRPCを実現する技術ではないので、従来のプログラミング的なデータ型とは異なる「型」という概念を理解しなければならない。例えていうなら、日本法令様式のような、特定のカテゴリで利用する伝票や、RosettaNetのPIP(Partner Interface Process)における送受信メッセージのスキーマなどがメッセージの型である。XML Webサービスとは、サービス側が指定するメッセージの型と一致しているメッセージ(型に対するインスタンス)を、サービスの利用者が送信するシステムである。利用者はサービスから返答を受け取るかもしれないが、その返答もまた、サービスから利用者への一方向のメッセージと解釈される(そのため、そこにも型の定義がある)。
では、XML Schemaでメッセージの型を定義して型付けを厳しくすれば、システムは疎結合になるのだろうか。この疑問に対する答えも“No”だ。この非常にいい例が、先日から話題になっている「Google Webサービス」である。Google Webサービスでは、WSDLファイルの中にメッセージの型を定義している(http://api.google.com/GoogleSearch.wsdl)。以下はその抜粋だ。
Google Webサービスで定義されているWSDL(抜粋) |
このWSDLは、「WSDL仕様には不要な部分が多すぎる」という問題を端的に表現する素晴らしい例だ。このことは今回の趣旨から外れるので詳しく解説しないが、メッセージの型を定義する方法がWSDLでは2つあることが分かるだろう。それはさておき、WSDLを見ると、doGoogleSearchというoperationは、それぞれmessage要素とtypes要素で定義されている型にのっとった入力メッセージを受け取り、出力メッセージを返却することが分かる。それぞれの要素の型は、stringやintというXML Schemaの型として厳密に規定されている。これは厳しい型付けの例といっていいだろう。
だが、GoogleのWebサービスAPIは疎結合システムではない。その理由は、GoogleのWebサービスの実装が、特定のWebサービス・クライアントの実装方法に依存しているからだ。.NET Frameworkにも、Javaベースのほとんどの実装にも、WSDLを読み取ってクライアントのスケルトン・コードを出力する機能が用意されている。これらの機能を使うと、GoogleのWebサービス実装が暗黙に期待しているとおりの実装ができる。Googleが暗黙に期待しているのは、入力メッセージにおけるpart要素の順序だ。WSDLには順序を示す構文が一切使われていない(operation要素にparameterOrder属性を付ければ厳密な順序指定が可能)。指定されていない以上、例えばkeyパラメータをメッセージの最後の要素にしても問題ないはずだ。だが、現実にはそのようなSOAPメッセージを送信すると、“signature mismatch”というタイプの例外(エラー)がサーバから返される。つまり、GoogleのWebサービス実装は、ある特定のWebサービス・クライアントの実装コードと「密結合」しているのである。
Googleの場合、WSDLそのものが問題なのではない。WSDLには厳しい型がきちんと付けられている。プログラマに対して「厳しい型付け」というと、メソッドの戻り値やパラメータの順序を変更できないという意味にとらえられがちだが、XMLの世界では必ずしもそうではない。上記のGoogleのWSDLのように、メッセージの型が決まっているにもかかわらず、パラメータの順序は変更できたり、場合によっては要素を後から追加したりすることも不可能ではない。XML Schemaの型システムはプログラミング言語の型システムよりも柔軟性に富んでいる。GoogleのWSDLはその柔軟性を生かして定義されている。単純に、実装がそれに追いついていないのだ。その結果、ある特定の実装だけに密結合したWebサービスになってしまっている。Googleがもしもパラメータの順序の入れ替えをサポートするつもりがなかったのなら、最初から要素の出現順序を明示すべきだったのだ(XML Schemaにはその機能がある)。あたかも仕様上は入れ替え可能なように書いておいて、実際には特定の実装に合わせて入れ替えしないことを前提にしているので、疎結合でなくなってしまっている。
疎結合システムを開発するには、現状のほとんどのツールで行われているような、コードを書いてからWSDLを出力するやり方では恐らく駄目だろう。そうではなく、まずメッセージの型の定義を厳密に行うべきだ。メッセージの型が決まったら、その型のメッセージのやりとりを定義するWSDLを作成し、そのWSDLからソース・コードのスケルトンを出力して実装に入ることになる。.NET FrameworkならWSDL.EXEの“/server”オプション、Javaならwsdl2javaの“--skeleton”オプションがサーバ側スケルトンの出力をサポートしている。
メッセージの型の定義作業は恐らく何日も、場合によっては何カ月もかかるだろう。自社のビジネスにおいて必要な情報がメッセージにすべて含まれていて、しかも変更が加わりやすい部分(ホットスポット)に柔軟に対応できる(例えば要素や属性を後から追加できる)ような型を定義しなければならない。この作業がかなり面倒であるからこそ、いまさまざまな産業界がそれぞれの中で通用する統一的なXMLボキャブラリを作ろうとしているし、RosettaNetやebXMLのような場所で業界横断的な仕様が規定されようとしている。これらの作業は、ひと言でいって「メッセージの型の定義」そのものだ。
XML Webサービスの開発において最も気を配るべき点は、「型付けが強く、結合が緩やかな」システムにするということだ。現状のツールを正直に使ってしまうと、「型付けが弱く、結合が緊密な」システムになりがちだが、この組み合わせは最もたちが悪い。サービスの利用者にとって、何が前提になっていて、どんなメッセージを送ればどんなことが起きるのか、客観的に判断できないからだ。客観的に判断できないと、ツールによる支援が受けにくいことはいうまでもないだろう。従来のように「あとは運用で」とごまかそうとすると、このようなシステムに陥りがちになる。疎結合システムの開発は、XMLを使えばいいというような単純なものではないのだ。
吉松 史彰(よしまつ ふみあき)
インフォテリアにおいて、.NET FrameworkやXMLを活用したシステムの開発とコンサルティングを行っている。また、個人でも執筆や講演活動を通して.NET Frameworkの啓蒙活動をマイクロソフトに黙って勝手に行っている。
「Insider.NET - Opinion」 |
- 第2回 簡潔なコーディングのために (2017/7/26)
ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている - 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう - 第1回 明瞭なコーディングのために (2017/7/19)
C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える - Presentation Translator (2017/7/18)
Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|