BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ アーティクル コントラクトのバージョニング、互換性、およびコンポーザビリティ

コントラクトのバージョニング、互換性、およびコンポーザビリティ

ブックマーク

この数週間、多くの業界アナリストは、SOAについて、すぐさま不安や不確実さ、疑問を指摘しました。たとえば、Gartnerは、SOAイニシアチブを始める計画を持つ会社が減少している一方で、SOAイニシアチブを計画しない会社が過去12か月に6~16%増加している、と述べています(サイト)。これらのメモや記事から、会社がもはや、様々なソリューションで構成できる再使用可能なIT資産の形成を良いものとは考えていないことがうかがわれます。

我々は、SOAへのこの興味の低下には、まったく異なった説明ができると考えています。SOAイニシアチブの重大な失敗の1つは、まさに、再使用可能で構成可能な資産を生成することができない点です。新しい消費者は皆、既存のサービスとは異なるサービスを必要とするフレッシュな要件をもたらすかのように見えます。サービスは、従来のソリューションアーキテクチャと比較すると、設計、構築、運用により費用がかかるので、これらのサービスを再使用できないと、SOAは、そのビジネスケースの大部分を実現できません。我々の経験では、サービスの原始的な再使用を越え、SOAの見込まれた効果を達成できた会社は、ほとんどありません。

サービスの再使用を望んでいる場合、このサービスが何を提供するか、それはどのように消費できるかを表現するコントラクトに対して、明瞭なデザインガイドラインを持っていることが絶対必要です。SOAガバナンスが多くなくても、SOAイニシアチブを開始できるかもしれませんが、コントラクトのデザインガイドラインを持っていないのは間違いです。時間がたてば、これらのデザインガイドラインは、もちろんSOAガバナンスのデザインコンプライアンスポリシーの中心になります。しかしながら、業界は全体として、しばしば“Just a Bunch of Web Services” (JaBoWS)と一蹴されているように、うまく再使用可能な資産を構築する方法として、SOAガバナンスプロセスに重点を置いてきたように見えます(サイト)。しかし、この戦略は、この目標を達成するのに十分であるか、まだ証明されていません。

我々は、SOAガバナンスは必要であるが、長期間にわたる資産の再使用に必要なレベルのサービス仕様を通常は提供できない、と主張しています。SOAガバナンスは重要です。そして、実際的なできるだけ多くのガバナンスが、サービスを識別、指定、設計するときに実施されるべきです。しかしながら、リソースや時間の制限および3~6か月をはるかに越えた未来を予測できないために、ガバナンスのみでは、再使用可能な資産を生成できません。必然的に、新しく予期しないサービス消費者が、既存のサービスの進化を必要とする、新しい要件とともに現れます。適切なバージョニング戦略なしでは、サービスの新バージョンは、まったく新しいサービスになってしまい、類似しているが別個のレジストリ項目やコードベース、ライフサイクルのニーズを生み出します。適切なバージョニング戦略を持たない組織は、同じサービスの複数の「バージョン」をしばしば生産環境に展開、運用、維持します。これは、SOAの利点と投資収益率を大きく制限し、「再使用」はSOAイニシアチブの一部として期待すべきではないと主張するアナリストからのコメントをあおります。 (サイト)

この記事では、我々は、サービスの再使用、コンポーザビリティ、および以前の消費者(またはプロバイダー)との互換性に向けた、サービスコントラクトバージョニング戦略を確立するための、一連の推奨案を提供します。我々は、そのようなバージョニング戦略は、満足なレベルのサービスの再使用を達成し、逆にSOAイニシアチブからより高い(そして期待された)ROIを生み出すのに不可欠であると主張します。

コントラクトの要素

「コントラクトは、SOAで最も重要なメタデータである」とZapThinkのアナリスト、Ron Schmelzerは言います(サイト)。サービスプロバイダーとサービス消費者の間のコントラクトには、多くの部分があります(サイト)。これらの要素のいくつかは、機械可読形式にすることができます。いくつかは、たとえばXML Schema、WSDL、およびWS-Policy仕様のような技術を使用して、実行時に実施可能にすることもできます。一方で、他の要素は、依然としてほとんど人間だけが消費します。

この論文の目標は、回線を進むビットの形式や順序から、サービスレベル合意または(たとえばプライバシーに関する)法律上のステートメントに至る、コントラクトのあらゆる要素を検討することでは必ずしもありません。むしろ、我々は1つの単純な問題に注目したいのです。既存の消費者またはプロバイダーそれぞれの互換性を維持したまま、サービスプロバイダーまたは消費者の進化をサポートする戦略の定義です。我々は、この戦略は、SOAの利点を提供する中核であり、(ガバナンスのニーズを縮小するので)サービスを構築する初期コストおよび継続的なサービスの保守、運用コストをbreakingに削減できる、と考えています。

提案するバージョニング戦略は2つの部分からなります。

  1. サービス消費者とプロバイダーの両方が実行時に実施する全ルールを示す、機械可読形式のコントラクト要素を作成する
  2. サービス消費者とプロバイダーによって同意されたコントラクト要素の、バージョン間の互換性ルールの集合を作成または活用する

機械可読形式のコントラクト要素は、バージョニングの基礎となります。サービス消費者とプロバイダーの両方が、このメタデータを使用して、エンドポイントで送受信した現在のメッセージを、正当に処理するか、また処理できるかを判断できる、また判断しなければならないからです。これらの要素は、あるメッセージの成功しそうな処理に対して一番低いバーを定義します。もちろん、サービス実装のビジネスルールは、コントラクトの例外を返すことができます。

1つの戦略としては、機械可読形式のコントラクト要素を定義せず、消費者またはプロバイダーのいずれかがその問題を解決するまで、消費者またはプロバイダーがメッセージを処理できないたびに、例外を交換し続けることも可能です。たとえば、RESTコミュニティのメンバーは、機械可読形式の要素が必要でなくなる「uniform contract」の採用を主張しています(サイト)。それは、サービスの実装、検証、または設定を支援する間に、明白なセマンティクスを他の方法で提供できたでしょう。 しかし、RESTコミュニティは、RESTfulなWebサービスが、互換性を持ちながら進化できるという証拠を提供していません。

問題は、どのコントラクト要素が必要かというよりは、サービスプロバイダー(または消費者)の2つのバージョン間の互換性の表現を容易にする方法にあります。言いかえれば、消費者が新バージョンのサービスプロバイダーと対話する場合に、我々は前のバージョンと同等の振る舞いを期待しているか、ということです。単に特定の場所でメッセージを送受信することに同意するような「uniform contract」を採用することは、互換性の問題に答えるのに役立ちません。

この記事では、我々は、受信SOAPメッセージが正当であるかどうか確認するのに必要なメタデータに注目します。したがって、我々は、WSDL文書(Wikipedia)で定義されるコントラクト要素に注目します。WSDL 2.0の使用はまだ広く普及していないので、我々はWSDL 1.1を使用します。WSDL 2.0にこの戦略を適用する際、breakingな変更はないと考えています。WSDL 1.1の要素(サイト)には、次のものが含まれます。

  • サービス定義対象名前空間
  • メッセージタイプ
  • メッセージ定義
  • 障害
  • ポートタイプ
  • バインディング
  • サービス定義
  • WS-Policyを使用して表現されたオプションのポリシー

 

図1 WSDL 1.1.コントラクトの要素

バージョニングのガイドライン

サービスとスキーマのバージョニングは、3つのタイプの互換性シナリオ(図2)に至る可能性があります。

  • 互換性なし
  • 前方互換
  • 後方互換

旧バージョンのコントラクトを利用する消費者をサポートし続ける新バージョンのコントラクトは、後方互換性を持つと見なされます。

未知の将来の消費者をサポートするよう設計されているコントラクトは、前方互換性を持つと見なされます。そのようなコントラクトは、消費者が時間とともに進化すると予想しており、XML Schemaのワイルドカードを通して拡張性をサポートします。この種の互換性は、しばしば、より遅いペースで進化するかもしれない複数のサービスプロバイダーを消費者が利用する、B2Bのシナリオで見られます。企業では、最も一般的なシナリオは後方互換性です。

後方互換性とは、「互換」という言葉が通常意味するものであり、non-breakingな変更がコントラクトに行われるときに可能です。コントラクトにbreakingな変更を加えると、必ず互換性が失われます。これらのシナリオは、たとえばJohn Evdemon(サイト)やDave Orchard(サイト)によって、文献で広く説明されています。

コントラクトは後方互換性と前方互換性の両方を持つことができる点に注意してください(サイト)(後でこれについて説明します)。

図2 サービス運用互換性シナリオ

前方シナリオおよび後方シナリオのための、Webサービス技術のサポート度は、分散コンピューティング技術の世界において匹敵するものがありません。RPC、CORBA、DCOM、JEE(サイト)のいずれも、単に特定のデザイン制約条件の適用により、即座にこれらのシナリオをサポートすることはできません。 実は、これらのシナリオをサポートする能力が、疎結合と再使用の達成の鍵となります。

サービスが後方互換性を持つように進化するとき、より多くの消費者がそれを再使用でき、その時、既存の消費者の実装または設定の変更を必要としません。ガバナンスが将来の消費者のニーズを予測できなかったとき、または予算のためにV+0で必要な全機能を備えることができなかったとき、互換性を持つサービスバージョニングは、既存の消費者の活動に影響を与えることなく、更新を可能にします。特に、このようにして"JaBoWS"は、ゆっくりとしかし確実に企業クラスのサービスへと進化し、広範囲の消費者に役立ちます。

互換性は、明示されたバージョニングスキームによって定義されます。

  • メジャーバージョン: 非互換(breakingな変更)
  • マイナーバージョン: 互換(non-breakingな変更)

breakingな変更とは、たとえば、既存のオプション要素を必須要素に変更したり、新しい必須要素を追加したりといった、受信入力メッセージの処理が失敗する、既存のスキーマタイプへの変更です。non-breakingな変更とは、たとえば、新しいオプション要素の追加です。スキーマやサービスに対するnon-breakingな変更は、マイナーバージョンとして登録され、breakingな変更は、必ず新しいメジャーバージョンとして登録されます。

サービスのバージョン管理可能なアーティファクトはすべて、変更によって影響されます。また、これらの変更は下から上へとアーティファクトに波及し、この波及効果は最終的に消費者に影響を与えます。この波及効果を表1で説明し、図3に示します。バージョニングにより変更の影響をコントロールできますが、互換性は、バージョニングの負の効果のいくつかを和らげるのに役立ちます。

図3 変更の波及効果

以下では、サービスのバージョンが、メジャーバージョンを使用すると互換性を持たず、マイナーバージョンを使用すると互換性を持つバージョン(前方または後方)になることを述べます。ポイントバージョンは、コントラクトの変更を含んでおらず、実装、配備または構成の変更(たとえば、バグの修正、新しいサービスコンテナのリリースなど)に限定されるバージョンを示すために使用されるべきです。ポイントバージョンは、定義上必ず互換性を持ちます(ここでも、これはステートメントであり保証ではありません)。

アーティファクト 変更 メジャー マイナー ポイント
サービス Breaking X    
サービス Non-Breaking   X  
合成サービス 非互換スキーマサービス X    
合成サービス 互換サービス   X  
サービス 非互換スキーマ X    
サービス 互換スキーマ   X  
スキーマ Breaking X    
スキーマ Non-breaking   X  
スキーマ集約 非互換スキーマ X    
スキーマ集約 互換スキーマ   X  
コード バグフィックス / 保守     X
コード 安全な変更   X  
コード 意味的な / 安全でない変更 X    
他のサービスアーキテクチャ 任意     X

表1 コード、スキーマ、およびサービスに対する変更のバージョニング波及効果

メッセージタイプスキーマを設計するとき、これらの単純なルールを使用して、2つのメッセージタイプが互換性を持つと明言できます。

  • XML Namespaceの値は、あるメッセージタイプとあるメジャーバージョンに対しては不変でなければならない。
  • メッセージタイプスキーマは、たとえばタイプxsd:intを使用して、メッセージタイプのルート要素上の必須のマイナーバージョンとポイントバージョンのカスタム属性を含む必要がある。
  • XML検証を使用してもしなくても、各メッセージ消費者は、受信メッセージのメジャーバージョンが、自身の実装バージョンと一致していることを確認しなければならない。メッセージの発信者と受信者のメジャーバージョンが一致しないときは、例外を返す必要がある。

.Netの世界では、Message Typeアーティファクトもデータコントラクトと呼ばれます。

Webサービス拡張性ガイドライン

後方互換性の原理は、十分に文書化されていますが、めったに適用されません(サイト)。(こちらを参照)(サイト)わかりやすいように、ここでそれらを詳しく説明します。

サービス定義の対象名前空間

WSDL対象名前空間は、メッセージタイプXML Schema名前空間とは異なる可能性があります。ポイント、マイナー、メジャーのいずれのバージョンでも、サービスコントラクトまたは実装が修正されるごとに、WSDL対象名前空間は違っていなければなりません

SOAPアクションが、実行時までに自動的に定義される代わりに、手動で定義されている場合、この名前空間は実行時に使用されません。したがって、WSDL定義はすべて、手動で定義されたSOAPアクションを含む必要があります。[1]

メッセージタイプ

メッセージタイプスキーマは、XML Schema拡張メカニズムを利用して設計する必要があります(これらのメカニズムの詳細な説明を以下で行います)

メッセージタイプ名前空間は、サービスコントラクトのメジャーバージョンのみを参照し、互換性がないサービスバージョンを示す必要があります。マイナーバージョンは、ルート要素に対する属性として指定できます。

メッセージ定義

部品をメッセージ定義に追加できますが、XML Schemaの拡張ルールを使用して内容を拡張できるメッセージエンベロープを含む、1つの部品の使用を推奨します。

障害

新しいマイナーバージョンに関連付けたメッセージタイプの拡張に関係する場合を除いて、障害は既存の操作に追加できません。

ポートタイプ ポートタイプは、新しい操作で拡張できます。

操作のシグネチャおよび操作が呼ばれる順序(WSDLで指定されない)は変更できません。

バインディング

新しいバインディングを定義できます。しかし、既存のバインディングは、サービスのエンドポイントを含めて修正できません。

サービス定義

サービス定義は、新しいポートでのみ拡張できます。既存のポートは変更できません。

WS-Policyを使用して表現されたオプションのポリシー

ポリシーの互換性シナリオを評価するのに利用可能な一般的なフレームワークはありません

表2 サービス定義互換性デザインルール

XML Schemaを使用するメッセージタイプのデザインは、XSD拡張とも呼ばれる、後方互換性を達成するため注意深く計画する必要があります。

John Evdemonは次のように説明しています。(サイト)

XML Schema標準は、ワイルドカード使用要素として<xsd:any>を導入しています。<xsd:any>によって、スキーマを明確に拡張できます。<xsd:any>は、ワイルドカード内に現れる可能性がある要素の範囲を抑制または拡張するnamespace属性を含んでいます。namespace属性は、以下のいずれかに設定できます。

  • ##anyによって、いずれかのNamespaceからの要素を使用して、スキーマを拡張できる。
  • ##targetnamespaceは、targetNamespace内に現れる要素にワイルドカードを制限する。
  • ##otherは、targetNamespaceからの要素を使用して、スキーマの拡張を不正にする。

processContents属性は、パーサーがどのようにスキーマ拡張を検証するかを示します。

  • strictは、スキーマ拡張をすべて検証するようパーサーに要求する。
  • skipは、スキーマ拡張の検証をオフにする。
  • laxは、サポートされた名前空間からの要素を検証し、未知または予期しない要素を無視する(ほとんどのWebサービス仕様はlaxを使用します)。

 

XSD拡張に関しては、XML Schemaの1.0仕様に困難な点があります。UPA (unique particle attribution)ルール(サイト)のために、型定義の最後の要素として任意の数または無制限の数の要素を持つ、XML Schemaタイプの検証中に、曖昧さが存在します。そのため、そのタイプの最後の要素のカーディナリティが可変の場合、その要素を使用する前に、カーディナリティがちょうど1の特定の要素を追加しなければなりません。

たとえば、<eovmxmy>のような要素を選択したいと思う場合があります。ここで、xはメジャーバージョン番号、yはマイナーバージョン番号(eovはend-of-versionの略)

XML Schema1.1では、この曖昧さは取り除かれ(サイト)、この付加要素は必要ありません。

XML Schema拡張機能の使用は1つの方法です。しかし、より古いバージョンのメッセージ消費者が、より新しいバージョンのメッセージに遭遇したとき、まだルールの集合を定義し同意する必要があります。この新しいメッセージは、元のメッセージスキーマの拡張セクションのいくつかに該当する要素を持ちます。ここで問題となるのは、これらの要素をどうすべきか、という点です。我々は、消費者側の変更を必要としない後方互換性に至る、以下のルールの適用を推奨します。

  • 未知の要素に遭遇したときのサービスの振る舞いは、コントラクトの一部としての拡張処理ルールによって明確に定義しなければならない
  • 後方互換性を持つことを目指したメッセージタイプの新バージョンに追加された新しい要素は、以前のバージョンのメッセージタイプを無効にしてはならない
  • メッセージの消費者は、認識できないあらゆる要素を受け取り、処理から取り除かなければならない
  • 対応するリクエストと同じタイプを含むリクエストから生成されたレスポンスは、リクエストを処理する前に、取り除いた対応する要素を追加しなければならない

これらのルールにより、あらゆる消費者は、その実装で処理せざるをえない要素にXML Schemaの検証を使用できるようになります。我々は、ぞんざいな方法でXMLとXML Schema拡張を使用し、検証を省略することはまったく推奨しません(図4)。業界に広く普及した通説に反して、XMLとXML Schema拡張は、互換性ベースのバージョニング戦略にとって不可欠であり、したがって再使用の達成にも不可欠です。奇妙な運命ですが、この重要な技術的進歩は、業界の専門家やアナリストによってしばしば軽視されてきました。

消費者とプロバイダーの実装は、実装については非対称です。

  • 消費者がプロバイダーによって送信された受信メッセージを検証すれば、それらは検証に合格する(定義された実装ルールのため)。
  • しかし、もちろん、サービスプロバイダーの実装は、一般に受信メッセージのすべてのマイナーバージョン向けスキーマを追跡し、あるメジャーバージョンのマイナーバージョン番号に基づいて各受信メッセージを検証しなければならない。おそらくそのコールを実装の変種へとルーティングする必要さえある。

上部のマイナーバージョンスキーマは、より下位のバージョンスキーマを(一般に)検証できないからです。上部のマイナーバージョンは、より下位のマイナーバージョンスキーマで検証できない同じ対象名前空間における必須要素をたいてい持っています。

消費者のバリエーション

また、バージョニングとは異なる、XML Schema内の「拡張エリア」に対するニーズがあります(図4)。たとえば、消費者特有のバリエーションが必要なとき、拡張はよく利用されます。消費者とプロバイダーの間(他の消費者とは無関係)の特殊な関係が必要な場合です。これらの拡張は、すべての消費者に共通のコントラクトに埋め込まれた、特定の消費者とサービスプロバイダーの間の個別のコントラクトと見なすことができます。ここでも、これらの拡張を可能にするために戦略を持っていることは、よいレベルのサービスの再使用を達成するのに不可欠です。

  • 拡張は、一般的なバージョニングパターンとは別に処理しなければならない。我々は、メッセージタイプのルート要素の下で単一の要素を使用して、拡張を実装することを推奨します。
  • メッセージタイプで明確に定義されている場合やmustUnderstand='true'属性で指定されている場合を除いて、メッセージ消費者は拡張を処理してはならない。必須要素を処理できないとき、メッセージ消費者の実装は、例外を生成しなければならない。
  • メッセージタイプのルートとは異なる名前空間に拡張が所属することが推奨される。

図4 バージョニングとユーザー拡張の互換性

Webサービス技術で、ビジネスロジックの様々なバージョンによって同じ情報にアクセスするために、様々なエンドポイントを使用できるという事実は、対応するサービスの保守と運用を非常に単純化します。全体として、Webサービス技術、XMLおよびXML Schemaは、バージョニング戦略を指定する安定したコントラクトに依存できないRESTなど(サイト)、それより以前の分散コンピューティング技術とは異なり、互換性シナリオをサポートするかつてない機会を提供します。RESTでは、各リソース(インスタンス)がエンドポイントを露出するという事実は、エンドポイントとリソース(インスタンス)の間の強力な結合を生み出しています。このため、ビジネスロジックの実装の複数のメジャーバージョンを運用上管理することは困難になります。RESTには、この2つの間に間接化の層を導入する場所がないからです。リソースとエンドポイントの間のこの結合は、リソースタイプにバージョンを割り当てることを困難にします。RESTでは、リソースタイプは生存しません。また、各リソース(インスタンス)は、HTTP動詞と任意の名詞の特定のバージョンに関連付けられた、自身のバージョンのビジネスロジックを実装できるからです。

互換性とコンポーザビリティ

以前に定義された互換性シナリオは、最新のThomas Erlシリーズの書籍Web Service Contract Design and Versioning for SOAに定義されるように、これらの戦略へと統合することができます。(サイト)

  • Strict: どの変更も、安全でないと見なされ、新バージョン作成の原因とならなければならない。 non-breakingな変更は、新しいマイナーバージョンの原因となる。 breakingな変更は、新しいメジャーバージョンを必要とする。 後方互換性と前方互換性は両方とも、故意に無視される。
  • Flexible: non-breakingな変更は、新しいポイントバージョンを生むだけである。 もちろんbreakingな変更は、新しいメジャーバージョンを必要とする。 この戦略は、前方互換性を持つコントラクトではなく、後方互換性を持つコントラクトを使用する。
  • Loose: 後方互換性を持つコントラクトと前方互換性を持つコントラクトを両方とも使用する。 もちろんbreakingな変更は、新しいメジャーバージョンを必要とする。

"Strict"は、スキーマバージョニングの処理には、非常に一般的なアプローチです。コントラクトの変更時に驚きを与えない、安全なアプローチです。実際、上に示したスキーマアーティファクトバージョニングの表は、"Strict"戦略に基づきます。しかしながら、サービスが進化するにつれて、コントラクトのバージョンが爆発的に増え、再使用は言うまでもなく発見可能性、特にガバナンスを傷つけます。さらに、運用部門は、多くのサービスバージンを利用可能な状態に維持する必要があります。集約スキーマ(スキーマ構成)で使用されるスキーマに対する変更は、関連するすべての集約へと波及し、新しいスキーマバージョンのドミノ現象を引き起こします。また、もちろん、サービスで使用されるスキーマが新バージョンを手に入れると、そのサービスも新バージョンを入手しなければなりません。その後、これらのサービスに関連する合成サービスも影響を受け、新バージョンを手に入れなければなりません。このように、波及効果は、皆さんが考えるよりはるかに大きくなります。

このバージョニングのドミノ現象はすぐに、小さな変更が、システムのすべてのバージョン管理可能なアーティファクトへと波及する原因となります。また、そこにとどまらず、結局は消費者に影響するようになります。

サービスの発見可能性が不十分で、サービスバージョンが増殖していると、コンポーザビリティは被害を受けます。不運な消費者は、どのサービスを使用するべきか、また、どのサービスが合成サービスとして連携するか?標準化されたサービスとスキーマの何千ものバージョンがあるとき、自分のドメインのための共通情報モデルを含め、標準化したサービスコントラクトを持つことでは、十分ではないかもしれません。

"Flexible"は、non-breakingな変更をすべて安全で後方互換性を持つものとして扱うことにより、Strictのバージョン爆発の影響を緩和しようとします。後方互換性を持つコントラクトのデザインによる変更は、古いバージョンのコントラクトを利用する消費者をサポートし続けるので、新バージョンは必要ではありません。つまり、それはポイントバージョンにすぎません。メジャーバージョン内のコントラクトはすべて、後方互換性を持ち、あらゆるメジャーバージョンについて1つの(最新の)マイナーサービスバージョンだけを考慮すればよいので、サービスは簡単に構成できます。"Loose"を追加して、前方互換性を持つコントラクトを入手すれば、互換性とコンポーザビリティの問題はすべて過去のものになります。

理論上、これは、完璧なソリューションであるように見えます。breakingな変更だけが新バージョンを必要とし、したがって、すべてのバージョン管理可能なアーティファクトへと波及します。理論上というのは、機能上も非機能上も「安全な」変更の副作用がなかったら、ということです。Nicolai M. Josuttisがその著書SOA in Practice(サイト)で示すように、新しいオプションXML要素をさらに追加することが、サービス応答時間の増加などの非機能上の副作用となり、サービスのSLAに違反する可能性があります。 新しいサービスバージョンに新しいスキーマを提供するほうが安全です。問題があれば、変更が必要な、アップグレードされた消費者だけが影響を受けるからです。我々の提案した推奨では、互換性は暗示ではなく表明されているという点に注意してください。したがって、もしSLAが単一の要素によって変更されれば、たとえXML拡張性の観点から、この変更が完全な互換性を持っていても、新しいメジャーバージョン(およびXML名前空間)の定義が必要になります。

我々の経験では、これらを組み合わせるとは、より効果的です。

  • . Flexible/Strict:"Flexible" をすべての安全なスキーマの変更に使用し、"Strict"はスキーマに対する安全ではない変更に使用する。breakingな変更は、新しいメジャーバージョンを必要とする。 このアプローチは後方互換性をサポートする。

"Flexible/Strict"戦略は、3つの元の戦略の一番良い部分を組み合わせています。変更が理論的に後方互換性を持つ(つまりnon-breakingな変更)であっても、変更を安全なものと安全でないものに類別します。安全な変更から、ポイントバージョンが生まれ、安全でない変更からは少なくとも1つのマイナーバージョンが生まれます。どの変更が安全で、どれが安全でないかに、絶対的な分類体系はありませんが、スキーマへの追加は安全であり、既存のスキーマコンポーネントへの修正は安全でないと見なすことを推奨します。「安全な」変更でもマイナスの副作用をもたらす可能性があるかどうかを必ず判断し、忘れずに非機能的な側面を考慮してください。

戦略 変更 メジャー マイナー ポイント FW
Strict Breaking X      
Strict Non-Breaking   X    
Flexible Breaking X      
Flexible Non-Breaking     X  
Loose Breaking X     X
Loose Non-Breaking      X X
Flexible/Strict Breaking X     +
Flexible/Strict Non-Breaking, 安全     X +
Flexible/Strict Non-Breaking, 安全でない   X   +

表3 安全か安全でないかで分類した互換性を持つ変更

"Strict"の意味では新しいマイナーバージョンでなければならない変更がすべて、安全な変更に対するポイントバージョンになる可能性ができるので、"Flexible/Strict"の使用は、スキーマアーティファクトのバージョニングテーブルに影響を与えます。安全でないnon-breakingな変更は依然として新しいマイナーバージョンでなければなりません。コード変更が安全であると判断しても、これを新しいマイナーバージョンとすることを我々は推奨します。

スキーマは、それらのメジャーバージョンやマイナーバージョンに基づいて、検証されルーティングされます。このように、ポイントバージョン互換性を目指すことで、サービスにおける複雑なバージョニングメカニズムのニーズが縮小します。

"Flexible/Strict"戦略を公開されたサービスに使用し、計画された拡張性の形で前方互換性を使用することを推奨します。コントラクトが曖昧になり、発見可能性を損なうので、どこにでもスキーマワイルドカードを挿入するのは避けてください。John Evdemonは、「スキーマは、バージョニングを回避するためではなく、拡張性のために設計すべきだ」と勧めています。明白なワイルドカードを賢明に使用すれば、サービスのバージョニングを最小化するのに役立ちます。我々は、これらのガイドラインに従うことを強く推奨します。

システムが、柔軟で、時間の経過により起こる不可避な変更に適応できるように、互換性を持つコントラクトと複数のアクティブなサービスバージョンの組合せを使用してください。物事を単純にしておきましょう。何をするにしても、サービス内部のバージョニングを暗黙のうちになぜか自動的に行う処理を実装しようとしないでください。その代わりに、抽象的なエンドポイントでサービスを露出し、インテリジェントなルーティングを適用して、サービスの仮想化を達成し、サービス外でスキーマのダックタイピングを適用してください。

その段階に必要な機敏性のため、サービスの開発の間には柔軟な戦略を使用すべきです。サービスが公開(実働環境で使用)されてから、厳密なバージョニングの側面を適用します。そうしないと、消費者もプロバイダー開発者も非常に苛立たしい思いをするだけです。

プラットフォームが後方互換性をサポートする仕組みが異なることに注意してください。スキーマワイルドカードの使用を必要とするものもあれば、WCFのように前方互換性の暗黙の支援を得るものもあります。関連するプラットフォームが、後方互換性を持つスキーマと連携するか必ずテストしてください。機能するだけで信頼しないでください。相互運用性はコンポーザビリティに重要です。

データモデルとメッセージタイプDSL

分散コンピューティング技術の中核問題の1つは、情報とビジネスロジックの両方の処理の統合です。分散情報(REST/HTTP)の管理に優れているアプローチもあれば、ビジネスロジック(Webサービス)の呼び出しに優れた技術もあります。リモーティングテクノロジーとネーミングサービス・IDサービスを組み合わせて、この両方に対応しようとした技術は、情報アクセスとビジネスロジック呼び出しの両方が調和して共存する環境の提供に通常は失敗しています。たいてい、Data Transfer Objectパターンのようなパターンが、優勢な対話モードになっており、情報表現は、サービスを表現するエンドポイント(つまりビジネスロジック)どうしの間でやりとりされるだけです。

この問題のソリューションに欠ける基本的理由の1つは、Enterprise Dataが「リレーショナル」であり、多くの場合、双方向の関連付けを利用するからです。対照的に、ウェブは「ナビゲーショナル」データモデルと一方向のリンク上に構築されます。ナビゲーショナルとリレーショナルのいずれの場合でも、同じエンドポイントを通して非正規化された方法でデータをフェッチする必要が必ずあります。つまり、注文書をフェッチするとき、発送情報だけでなく顧客特有の情報(氏名、住所、電話番号…)も返すかもしれないのです。使用するのがRESTfulなアプローチでもWebサービスのアプローチでも、問題はまったく同じです。注文書の表現内に顧客へのリンクを埋め込むことができるので、RESTの方がもちろん、この問題に対する標準化されたソリューションを提供するには少しは適しています。しかし、通常、関連データを埋め込み、ユーザー体験を向上させ、ナビゲーションとネットワークの往復を制限するためにしばしば必要とされる表現ほど、これは実際的ではありません。

この論文の目標は、この分散情報の統合問題を解決することではありません。どういう訳か、RESTとWebサービスの世界の両方でエンドポイントの後ろでしかそれを扱うことができないと想定することにします(これは、さらなる進歩が分散コンピューティング技術で見られるまでの現在の状況です)。この環境では、扱う必要がある問題は、特にバージョニングのコンテキストで、つまり、企業データモデルの改訂が必要なときに、非標準化されたメッセージタイプを管理する方法です(図5)。

図5 企業データモデルとメッセージタイプの同期をどのように維持するか?

これまで、業界は、Enterprise Data Model、XML Schemaおよびメッセージタイプを比較的個別に扱ってきました。せいぜい、両方へのリンクを使ってオントロジーを定義した程度です。 この記事では、我々は次のように主張します(図6)

  • XML Schemaは、企業データモデルを作成、管理するために使用すべきでない。
  • Enterprise Data Modelは、DSLに基づいて作成し管理すべきである(EDM-DSL)。
  • メッセージタイプは、DSLに基づき、構成部分としてEnterprise Data Model要素を使用して、作成し管理すべきである(MT-DSL)。
  • XML Schemaは、メッセージタイプDSL(自身がEnterprise Data Modelの参照要素)から生成すべきである。

図6 Enterprise Data ModelとメッセージタイプDSL

1つずつこれらのポイントを検討しましょう。XML Schemaはそれ用に設計されなかったので、XML SchemaをEnterprise Data Modelの作成と管理に使用すべきではありません。XML Schemaは、企業データモデルのリレーション的な性質を効率的に記述できません。XML Schemaは本来階層的で、情報エンティティの双方向関係をうまくモデル化できません。XML Schemaは、メッセージタイプやウェブページ、オフィス文書のどれであっても、自立した「文書」の構造を記述し検証するのに適した技術です。

Enterprise Data Modelは、DSLに基づいて作成し管理すべきです。現在のモデリング技術は、UMLでもエンティティ関係図(ERD)でも、Enterprise Data Modelについて記述するために適切なセマンティクスを持っていないからです。コアとなるセマンティクスが欠けていて、そのため既存の技術には役に立たないというのは、逆に言えば、関連する要素の階層構造について記述する能力を持っているということです。言いかえれば、UMLであれERDであれ、我々は、注文書や顧客の境界を定義するためのセマンティクスを持っていないのです。クラスやエンティティを定義できますが、実際には、注文書や顧客は、いくつかのクラスから事実上「構成」されています。これらのオブジェクトに対する境界を定義できる必要があるのですが、「標準的な」モデリング言語は、このセマンティクスをサポートしません。それら自身が物理的な実装モデルに近すぎるからです(UMLの場合はオブジェクト指向、ERDの場合のRDBMS)。UMLの場合には、UMLをこれらのセマンティクスを使って拡張するためには、UMLプロフィールを定義しなければなりません。しかしながら、UMLプロフィールを使用する代わりに、専用のデータモデルDSLを作成することを推奨します。UMLのメタモデルにより整理され、変換がずっと簡単なためです。

メッセージタイプは、Enterprise Data Modelの要素を参照する専用のメッセージタイプDSLに基づいて定義すべきです。根本的には、メッセージタイプは実際にこのように構築される(または少なくとも構築されるべき)だからです。RESTfulベースでもWebサービスベースでも、サービスインタフェースを作成するとき、あるバックエンドシステムの特殊性を反映する代わりに、企業データモデルを意味論的また構造的に反映するメッセージタイプ(またはリソース表現)を作成したいと考えます。これは、「コントラクトから実装まで」の結合を最小化することを推奨する、疎結合実践に一致します。Enterprise Data Modelのセマンティクスに基づいたアプローチは、両方のガバナンスのニーズを減らし(または、少なくともデータガバナンスの労力を再利用し)、おそらく再使用、構成可能なサービスインタフェースまたはリソース表現を作成することが期待されます。

最後に、水平なXML Schemaを、これらのメッセージタイプ定義(自身がEnterprise Data Modelに基づく)から生成すべきです。スタックには、複雑な入れ子状のスキーマファイルを扱うのに苦労するものもあるので、水平なスキーマは、Webサービススタック間の相互運用性を改善します。XML Schemaは、構造および「文書」の内容(の一部)を検証する、優れた技術です。これからも、受信メッセージの構造について記述し内容を検証する主要な選択肢であるべきです。

アクティブなサービスバージョン

サービスバージョンの管理を支援するために、サービスライフサイクル管理のポリシーと手順を実装することは重要です。最低管理しなければならない数のサービスバージョンを維持するため、「アクティブなサービスバージョン」ポリシーの作成を推奨しました。悲しいかな、我々の経験によれば、実際、これに従うのは難しいので、ポリシーは規則ではなくガイドラインとして実装します。

そのようなポリシーは、消費者に利用可能なサービスには最大3つのアクティブなバージョン、それに加えて、最新のメジャーバージョンの隠されたアクティブなマイナーバージョンが必要であると通常述べています。隠されたマイナーバージョンは、互換性を持つバージョンに戻ることができる移行期間を現在の消費者に提供します。最新のマイナーバージョンに関する互換性のステートメントが万一誤っていた場合に備えるためです。その場合、消費者は、手動で以前のマイナーバージョンのエンドポイントをポイントします。

図7 サービスバージョンの分類

特に多くの消費者が利用する人気のあるサービスでは、通常、5または6のメジャーなアクティブサービスバージョンを必要とするサービスができます。新しいサービスバージョンにアップグレードするのが遅い消費者が必ずいて、それらの消費者を閉め出すことはできないでしょう。しかしながら、我々が推奨しているアプローチでは、利用可能な全メジャーバージョンについて、各最新マイナーバージョンだけを露出する必要があります。

必ずデフォルトで、新しい消費者は、サービスの公開されたバージョン(つまり最新のメジャー/マイナーバージョン)を発見するようにしておきます。公開バージョンは、開発者が、サービスのクラッシックなhttp://url?WSDL「発見」を使用して入手します。さらに、サービスレジストリでサービスの3つのメジャーバージョンを発見できるようにしておくことを勧めます。これらは、それぞれの最新のマイナーバージョンでなければなりません。

最後に、どれが誰によって使用されているかを知るために、サービスの使用をモニタする必要があります。サービスライフサイクル管理者は、廃止予定のバージョンを全消費者に通知し、アクティブなサービスバージョンにアップグレードすることを消費者に穏やかに強制しなければなりません。(重要な)人間が誰も廃止予定のバージョンを使用しなくなれば、それを廃止できます。これで、そのサービスバージョンのライフサイクル管理が終わります。メジャーバージョンと複数のマイナーバージョンの両方に同じことをしなければならない場合、管理者の仕事がどれくらい困難になるか、簡単に想像できます。

アクティブなサービスバージョンは、サービスを呼び出すために消費者が使用する単一の仮想エンドポイントを通してアクセスできる必要があります。仮想エンドポイントは同じままで、適切なアクティブサービスバージョンに対するルーティングを処理するので、これにより、サービスへのバージョニングが消費者に及ぼす影響が小さくなります。同じエンドポイントが互換性を持つ消費者の複数の世代にサービスを提供できるので、互換性は、仮想化の必要性を小さくします。サービスは、そのメジャーバージョンやマイナーバージョンに基づいてルーティングされ、したがって、ポイントバージョンの互換性を目指すことにより、複雑な仮想エンドポイントメカニズムの必要性も小さくなります。

抽象的なエンドポイント、インテリジェントなルーティング、スキーマの変換など、いくつかのESBパターンを組み合わせて、サービスの仮想化が実現されます。サービスの仮想化の使用は、プロバイダーから消費者を分離し、メッセージを「飛行中に」処理します。そして、イベントを通して消費者が呼び出しトリガする合成サービスを構成するバージョンとプロバイダーとの間でルーティングやメディエーションを行います。

仮想化の使用は、合成サービスのみに向けたものではありません。実際、分類レベルに関係なく公開されたサービスすべてが、ガバナンスの観点から見ると、これから利益を得ます。

相互運用性

経済はますますグローバル化し、アウトソーシングは、最近では標準であるように見えます。たいてい、企業のビジネスプロセスは、パートナーとサプライヤが一体となった、いわゆる拡張企業(extended enterprise)に関与しています。

企業の様々な事業単位が、雑多なシステムを持つように、拡張企業の構成要素も雑多なシステムを持ちます(図8)。今日、企業で使用しているレガシーシステムの多様性に終わりはありません。最近のGartnerの研究によれば、SOAを提供するために使用されるプラットフォームの多様性は増大しています。メインフレームのCOBOLさえ前年急増しています。

拡張企業のこれらの雑多なサービスプロバイダーを横断したコンポーザビリティは、相互運用性を必要とします。相互運用性は、WS*標準のどれをサービスで必要とするかを決めるかなど、どのようにサービスとスキーマを設計するかに影響します。我々の相互運用性における経験を下の表に要約します。

アーティファクト 相互運用性
SOAP WS-I Basic Profile 1.1に準拠
SOAP 1.2 ほとんどのレガシープラットフォームとツールはSOAP 1.1を必要とする
WSDLスタイル "Document/Literal Wrapped" (D/L-W)を好む
WSDLデザイン 多くのツールが単一の水平なWSDLを必要とするので、wsdl:importおよび xsd:importを避ける。たとえばFlex。
メッセージ たとえばWSDL 2.0で定義されたメッセージ交換パターン(MEP)を使用する
メッセージデザイン リクエストとレスポンスの両方に1つの部品要素
スキーマスタイル "Venetian Blind"(複素数型)を好む。
スキーマスタイル 無名タイプ("Russian Doll")を使用しない。
スキーマデザイン XSD拡張性をサポートし、スキーマワイルドカードよりも前にマーカー要素を使用する。関連するプラットフォームを横断したスキーマワイルドカードのサポートを必ずテストする
スキーマデザイン D/L-Wスキーマコンポーネント。要素だけを許可し、属性の使用を禁止する
スキーマデザイン データへの属性の使用、データ要素を注釈するための属性の使用は、プラットフォームによりサポートされないかもしれない
スキーマ配列 wrapped配列/コレクションを使用する。
XSDタイプ すべてのXSDデータ型がすべてのプラットフォームでサポートされているとは限らない(たとえばxs:date、xs:positiveInteger)
XSD nillable いくつかのnillableスキーマコンポーネントはプラットフォームにサポートされていない可能性がある。一方で、他のコンポーネントは、nillableであることを要求されている可能性がある
WS*標準 サポートはプラットフォーム間で大きく異なる。選択した相互運用性を必ずテスト、確認する。
WS-Security バージョン、トークンタイプ、メッセージとトランスポートのセキュリティ、暗号化と署名の順序とレベル、および安全な対話(セキュリティセッション)の確立について必ず合意する。
WS-Policy、WS-SecurityPolicy プラットフォームとツールによっては、これらの標準をサポートしない。したがって、ポリシーメタデータは通信外で伝達しなければならない。Java Spring-WSがその例である。

表4 コントラクトのデザインガイドライン

 

図8 SOAプラットフォームでの多様性の増大

「開発言語の使用傾向はSOAの採用と関連する」という図は、Daniel SchollerによるGartnerレポート"2008 SOA User Survey: Adoption Trends and Characteristics"(サイト)からの引用です。

結論

この記事では、既存の消費者へのサービス提供を続けたまま、新しい消費者の要件を満たすようサービスを進化させることによって、再使用に注目するバージョニング戦略について説明してきました。このアプローチは、サービスの再使用に新しい次元を追加します。サービスの「新バージョン」が前の消費者によって再使用され、その逆ではないので、ある意味では、それは「前方」再使用戦略を導入します。従来は、既存のサービス消費者のために設計されたサービスを新しい消費者が再使用するときの再使用について、考察されてきました。

我々の経験から、互換性を持ちバージョン化されたデータモデル、メッセージ、およびサービスは、SOAイニシアチブの主要な関心事ではないと感じています。さらに、バージョニング戦略を定義したもののうち、ほとんどはXMLとXML Schema拡張を使用していません。互換性ベースのバージョニング戦略が、サービスの発見可能性、コンポーザビリティおよび真の再使用を向上させることができる、というのが我々の強い信念です。また、サービスガバナンスの必要を、なくさないにしても、小さくすることもできます。全体として、サービスの構築、運用および保守のコストは、このようなバージョニング戦略によって大幅に削減されることが期待されます。サービスインベントリの利点を収穫するため、原始的な再使用を乗り越える時です。

[1] Harmut Wilms, InnoQ, Private Communication

 

原文はこちらです:http://www.infoq.com/articles/contract-versioning-comp2

この記事に星をつける

おすすめ度
スタイル

こんにちは

コメントするには InfoQアカウントの登録 または が必要です。InfoQ に登録するとさまざまなことができます。

アカウント登録をしてInfoQをお楽しみください。

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

コミュニティコメント

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

BT