外部のデータと内部のデータ
サービス指向アーキテクチャがデータに与える影響の考察
By Pat Helland
Microsoft Corporation
概要: サービス指向アーキテクチャ、およびサービスの境界の内部のデータと外部のデータの違いに関する Pat Helland による論考です。 異なるデータ表現としてのオブジェクト、SQL、および XML の長所と短所についての議論や、これらのモデルの比較についても取り上げています。
目次
はじめに
サービスへの転換
サービス指向アーキテクチャについての前提
外部のデータ: メッセージの送信
外部のデータ: 参照データ
内部のデータ
データ: 過去または未来 (Then) と 現在 (Now)
データの表現: 内部と外部
まとめ
はじめに
これまでのところ、サービス指向アーキテクチャ (SOA) についての議論のほとんどは、異種システムの統合、企業の既存資産の活用、堅牢なアーキテクチャの作成などの問題を巡るものとなっています。 確かに、これらの問題はいずれも SOA に関連しています。 しかし、SOA については、注目に値する重要かつ興味深い問題が他にもあります。 さまざまな種類の独立したシステムの接続を目標とする SOA にはいくつかの主要な設計原則がありますが、 その 1 つに、独立したサービスにはメッセージングによって互いに接続されるコードとデータが含まれる、というものがあります。
実際、サービスとメッセージングの間には、切っても切れないつながりがあります。というのも、メッセージは、サービスの内部と外部を結ぶ唯一の手段だからです。 しかしその一方で、個々のサービスはそれぞれ独立して機能します。 このサービスとメッセージの間の独特の関係は、アーキテクト、開発者、およびプログラマにいくつかの重要な問題を投げかけてきました。 たとえば、サービス間のデータの流れ、メッセージの定義、共有するデータ、サービスの内部のデータとサービスの外部のデータの区別、サービスの内部と外部のデータ表現、などの問題がこれまでに検討されてきました。
その結果、サービスの内部にあるデータとサービスの境界の外部に存在するデータとの根本的な違いが明らかになりました。 サービスの外部のデータは、サービスの間でメッセージとして送信され、送信側と受信側の両方のサービスが理解できるような形で定義されている必要があります。 一方、サービスの内部のデータは、環境に深く根を下ろしています。 サービスの外部のデータとは異なり、内部のデータはサービス専用のデータです。 実際、外部のデータとの関連も緩やかなものにすぎません。
本論では、これらの成果を踏まえて、サービスの内部のデータと外部のデータについて詳しく論じます。 まず、不変データ、バージョン付きデータ、および参照データから成るサービスの外部のデータの種類を紹介します。 続いて、内部のデータに議論を移し、メッセージ (オペレータと応答)、参照データ、およびサービス専用データについて論じます。 その後、サービスの内部のデータとサービスの外部のデータの時間的な解釈について検討します。 どのような種類のデータがあるのかを特定できたら、次は視点をデータの表現へと移して、XML、SQL、オブジェクトという 3 つの重要なモデルについて検討します。
SOA によって企業間や IT 業界内の対話が引き続き促進されることになる一方で、今度はサービスの内部のデータとサービスの外部のデータが問題になる可能性があります。 現在、企業の間では、それぞれの環境に SOA をただ導入するだけでなく、サービスやサービスとデータの間の動作をより深く理解しようという気運が高まっています。
サービスへの転換
SOA ではまず、コードとデータを含む独立したサービスとそれを相互に接続するメッセージ、ということが問題になります。 各サービスはコードとデータから成る独自の集合体であり、他のサービスからは独立しています。 しかしその一方で、各サービスは、メッセージングを通じて他のサービスと相互に接続されてもいます。 この後者の特徴によってサービスは、さまざまな環境に存在するサイロから区別されます。
メッセージングは SOA においてきわめて重要な役割を担っています。 メッセージはサービス間で送信され、サービスの間を流れます。 各メッセージのスキーマ定義と、メッセージの流れを定義するコントラクトによって、サービスの "ブラック ボックス" の動作が規定されます。 サービスとメッセージングの間には、切っても切れないつながりがあります。というのも、メッセージは、サービスの内部と外部を結ぶ唯一の手段だからです。 パートナー サービスには、送受信されるメッセージの連鎖以外には何もわかりません。
図 1. サービスとメッセージの密接なつながり
多くの関連するメッセージが 2 つの異なるサービスの間で送信されることもあります。 関連するメッセージが数週間から数か月にわたって 2 つのサービスの間でやり取りされることもあります。 たとえば、2004 年 6 月 1 日に電車の乗車券を予約し、2004 年 6 月 5 日に予約の日付を変更し、2004 年 6 月 10 日に予約の確認と支払いを行い、2004 年 6 月 25 日に最終的に予約をキャンセルする、というようなことも可能です。この場合は、メッセージが数週間にわたって数日おきに送信されます。 このように長期にわたるやり取りを、長期の作業と呼びます。 長期の作業では各メッセージの間に関連があり、2 つ目のメッセージは 1 つ目のメッセージに、3 つ目のメッセージは前の 2 つのメッセージに、それぞれ依存しています。 長期の作業のメッセージを互いに関連付けるためには、Cookie やその他の同様の技術が使用されます。 この "長期の作業" という用語は、アトミックなデータベース トランザクションとの混同を避けるために、長期のトランザクションという用語の代わりに用いたものです。 また、トランザクションという用語には、始まりと終わりのある活動という意味が含まれますが、 ほとんどの長期の作業では、さまざまなビジネスに波及するような形で他のアプリケーションに影響が及ぶため、作業の始まりや終わりを示す明確な境界がありません。
図 2. 複数の関連するメッセージ
つまりメッセージは、SOA のなくてはならない重要な要素なのです。 後に示すように、メッセージが正しく解釈され、異なるサービス間のやり取りで混乱が生じないようにするには、特別な注意が必要です。
サービスとコンポーネント
関数、オブジェクトとコンポーネント、およびサービスは、長年にわたる自然な進化によって生まれました。 まず始めにコードが関数へと分離され、ソフトウェアをより小さく組織化された要素にまとめることができるようになりました。 その後、コンポーネントとオブジェクトの登場によって、データのカプセル化 (メンバ変数) が可能になりました。
現在、この進化のプロセスの主役となっているのはサービスです。 サービスでは、関数やコンポーネントに比べてコードの独立性が高い粗粒度の分離が実現されています。 第 1 に、サービスは常にメッセージを通じて他のサービスとやり取りします。 第 2 に、サービスには一般に耐久性があり、システム エラーや再起動があっても続行できます。 最後に、サービスの実装環境は非透過で、外部からはメッセージのやり取りしか見えません。
図 3. サービスとコンポーネント
内部と外部のデータについての考察
サービスの内部のデータとサービスの外部のデータを区別することが重要です。 サービスの外部のデータは、サービスの間でメッセージとして送信され、送信側と受信側の両方のサービスが理解できるような形で定義されていなければなりません。 一方、サービスの内部のデータは、環境に深く根を下ろしています。
少なくとも 2 つの異なるサービスでデータを解釈する必要があるため、共通のスキーマの存在および利用が不可欠です。 また、このスキーマはいくつかの特性を備えている必要があります。 第 1 に、スキーマ定義が独立していることが重要です。 つまり、送信側または受信側で、互いに問い合わせることなくメッセージ スキーマを定義できる必要があります。 第 2 に、メッセージ スキーマは拡張可能である必要があります。 これにより、送信側のサービスで、スキーマで指定されている以外の情報をメッセージに追加できるようになります。
メモ メッセージを送信するサービスがメッセージのスキーマを定義するとは限りません。
サービスの外部のデータとは異なり、内部のデータはサービス専用のデータです。 実際、外部のデータとの関連も緩やかなものにすぎません。 内部のデータは常にサービスのコードにカプセル化されているため、サービスのビジネス ロジックを通じてのみアクセス可能です。
図 4. サービスの内部のデータと外部のデータ
メインフレームとモノリシック アーキテクチャ (データに関する問題)
かつては、メインフレームやその他のサーバー システムで複数のアプリケーションをサポートするのが一般的でした。 各アプリケーションは共有データベースにアクセスし、一連の共有テーブルまたは同じデータベース内の異なるテーブルで作業を行います。 すべてのテーブルが大規模なサーバー上の共有データベースの中にあるため、多数の異なるテーブルのデータにアクセスする 1 つのトランザクションをアプリケーションで実行できます。 同様に、複数のテーブルを更新する操作でも、トランザクションのアトミック性のメリットを享受できます。 また、アプリケーションでデータベースのすべてのデータにアクセスできるだけでなく、別のアプリケーションが管理しているテーブルにもアクセスできるという点も、同じくらい重要です。 このことは、アプリケーション間の関係についての考え方に大きく影響してきました。というのも、この場合アプリケーションは、最新の (そして通常は最も正確な) 情報に即座にアクセスできるからです。 この種のアクセスには、セキュリティ、認証、プライバシーの問題などの条件もありますが、ほとんどのアプリケーションは、ただ参照するだけで最新の情報が得られると想定しています。
近年では、さまざまな経済的および技術的動向を受けて、アプリケーションが異なるマシンに配置されるようになってきました。 その結果、モノリシックなアーキテクチャは分断されることになりました。 標準的な組織では、もはやすべてのアプリケーションが 1 つの巨大なシステムで実行されることはありません。 しかし、そこには問題があります。アプリケーションが異なるマシンに配置されるようになると、データが異なるマシンに存在することになるため、同じデータを共有することが困難になります。 また、これらのマシンはそれぞれ独立して機能するように設計されており、通常はお互いの間に信頼関係がないため、これらのマシンにまたがったデータの更新も同じく困難です。
図 5. メインフレームとモノリシック アーキテクチャ
サービス指向アーキテクチャについての前提
サービス指向アーキテクチャの主要原則
これまでに、コードとデータ、システム、およびメッセージについて説明してきました。 現在議論されていたり、文章にまとめて紹介するだけの価値を持つ他のテーマと同様に、このテーマにもいくつかの原則があります。 以下に、サービス指向アーキテクチャの 4 つの主要原則の概要を示します。これらは、コードの存在、メッセージの形式と内容、サービスの機能、およびサービスの互換性について述べたものです。
- 明確な境界がある。これは、コードの各部分が存在する場所があいまいではない、という意味です。 具体的に言うと、コードがサービスの内部にあるのか、それとも外部にあるのかが明らかです。 データについても同じことが言え、 データベース テーブルがサービスの内部にあるのか、それとも外部にあるのかが明らかです。
- サービスは自律している。サービスには、それぞれ独自の実装、配置、および運用の環境があります。 したがって、サービスに変更を加えても、正しいメッセージが正しいタイミングで送信される限り、パートナー サービスに影響を与えることはありません。
- サービスはスキーマとコントラクトを共有するが、実装は共有しない。スキーマには、メッセージの形式と内容が記述されています。コントラクトには、サービスで送受信できるメッセージの順序が記述されています。 その一方で、実装方法については知らされません。 このことは、現金自動預け払い機 (ATM) を使用する場合を例にして考えるとわかりやすいでしょう。 ATM の使い方はほとんどの人が知っており、 どのボタンを押せばよいのか、ボタンを押すとどうなるのかが了解されています。 たとえば、暗証番号を入力し、いくつかのボタンを押す、という具合です。 このプロセス全体にコンピュータが関与しているであろうことはほとんどの人が知っていますが、 通常は、それがどのように実装されているのかまでは知りません。
- サービスの互換性はポリシーに基づく。サービスを利用するための正式な条件が存在します。 この条件は、サービスを使用するためのルールをまとめた英語のドキュメントに記載されています。 現在、WS-Policy が、ポリシーの要件をプログラムで宣言によって表現する方法の策定に取り組んでいます。
以上が SOA の基本原則です。これらがサービス間の関係の土台となっています。
SOA の問題
今日の企業を構成する複雑かつ膨大な IT システムに対処するには、どのような技術を用いたとしても、その原則や機能が継続的に問い直されることになります。 ここでは、サービス指向アーキテクチャが抱えるいくつかの問題に注目してみましょう。
これまでのところ、SOA では、明確な境界と自律性の 2 つが最大の問題となっています。 明確な境界は、サービスの内部にあるものと外部にあるものを明確に定義します。 サービスは、コードとデータで構成されています。 関数やコンポーネントとは違って、異なるサービスのコードとデータは互いに切り離されており、あるサービスのデータは別のサービスのデータに対してプライベートな状態に保たれています。 この切り離されたコードとデータの集合体は、サービスという明確な境界の中にあります。
自律性とは、サービスが互いに独立していることを指します。 たとえば、サービス A は常に サービス B から独立しています。スキーマとコントラクトが維持されている限り、悪影響を受ける恐れはありません。 結果として各サービスは、他のサービスとは関係なくコーディングや配置をやり直したり、完全に置き換えたりすることができます。
こうした自律性や明確な境界にもかかわらず、サービスの境界では、信頼関係を始めとするさまざまな問題が持ち上がります。 サービスの間には常に信頼関係が必要です。 そのためには、まずサービスでどのような種類の信頼関係が必要かを決定し、次に信頼関係の独自のスタイルを定義する必要があります。 信頼関係を定義するルールでは、企業間の実際のやり取りをモデルとするのが一般的です。 結局のところ、信頼関係について誰もがまず思い浮かべるのは、クレジット カード詐欺などの問題なのです。
トランザクションに関する議論
技術には、原則と問題に加えて議論も伴います。 どちらを向いても、常に何らかの技術についての議論が行われているようです。 SOA に関する重要なものとしては、トランザクションに関する議論があります。 この議論では、まず一方に、サービスの境界ではアトミック (ACID) トランザクション (おそらくは 2 フェーズ コミットによって実装される) を使用すべきだという意見があります。
メモ 現在、WS-Transaction が、サービスの境界にまたがるトランザクションの定義に取り組んでいます。
そして他方には、サービスが他のサービスに対してロックを保持するべきではないという意見があります。これは、ロックを保持するためには、許容される時間内にトランザクションが完了してレコードのロックが解除されるという、大きな信頼関係が必要になるからです。
この議論を詳しく分析してみると、それが実際にはサービスという語の定義に関する議論であることがわかります。 つまり、2 つのコードがアトミック トランザクションを共有する場合に、それぞれが独立したサービスとなるのか、それとも 1 つのサービスを構成するほど密接な関係を持つのか、という議論なのです。 2 フェーズ コミットによって接続されるコードがあるという点に変わりはありません。問題は、それらが同じサービス内にあるかどうかです。
本論では、2 つのサービスがアトミック トランザクションを共有しない場合に起こる問題に焦点を絞ります。 2 フェーズ コミットによってアトミック トランザクションを共有するコードもあれば、そうでないコードもあります。 複数の独立したコードがトランザクションを共有しない場合に何が起こるのか、ここではそれを検討します。 したがって、ここではサービスという用語に、独立性、自律性、および別のトランザクション スコープという意味を持たせています。
オペレータとオペランド
サービス指向アーキテクチャでは、サービス間のやり取りがビジネス機能を表します。 これらのビジネス機能は、オペレータと呼ばれます。 以下はオペレータの例です。
- Please PLACE-ORDER.
- Please UPDATE-CUSTOMER-ADDRESS.
- Please TRANSFER-PAYMENT.
オペレータは 2 つのサービスの間のコントラクトの一部であり、常に、サービスのビジネス上の意味に関するものとなっています。 オペレータはまた、オペレータの受け入れを示す一種の確認として使用することもできます。 たとえば、次のような例が考えられます。
- Acknowledge receipt of PLACE-ORDER.
- Acknowledge completion of TRANSFER-PAYMENT.
確認には、ビジネスで定義される奥行きがあります。 結果として、振り込みに対する要求の受信の確認と振り込みの完了の確認の間には違いがあります。 これはすべて、コントラクトでビジネス上の意味を明確に定義することへとつながります。
オペレータ メッセージには、さまざまなオペランドを含めることができます。 オペランドは、操作を実行するために必要な情報として定義されるもので、 送信側のサービスによってメッセージに配置される必要があります。 最も単純な場合、オペランドはメッセージのパラメータとして機能します。 たとえば、注文を行う顧客の ID や、注文に含まれる製品の SKU 番号などがオペランドになります。
図 6. オペランドを含むオペレータ メッセージ
では、サービスはどこでどのようにして使用するオペランドを取得して、オペレータ メッセージを準備するのでしょうか。 オペランドは参照データから取得されます。参照データは通常、オペレータのターゲット サービスによって発行されます。
参照データは、SOA の比較的新しい種類のデータです。 "比較的" という言葉を使ったのは、SOA はさまざまな形で、MQ、EDI、およびその他のメッセージング システムと共に、何十年も前から存在しているからです。 また、すべてがコンピュータ化される前にも、SOA スタイルの操作が手作業で行われていました。 たとえば、デパートの商品を注文する顧客は、注文書に必要事項を記入して、それを郵送していました。 この場合は、デパートの商品カタログが参照データで、デパートの注文が SOA の操作です。
図 7. 参照データの発行とオペランドの使用
外部のデータ: メッセージの送信
データの不変性とバージョン付け
データにはさまざまな形式があります。 データの種類としては、まず不変データがあります。 不変データは基本的に、一度書き込まれると変更はできません。 現実の世界のあらゆるところで不変データを見つけることができます。 たとえば、次の情報はいずれも変更できず、不変データの例と言えます。
- 1975 年 6 月 3 日版の New York Times
- 出版された書籍の初版
- 米国大統領のテレビでの発言
すべての不変データには識別子があります。 この識別子によって、いつどこで要求しても常に同じデータが得られることが保証されます。 したがって、同じ識別子を使用すれば、同じビット パターンを取得できます。 たとえば、Joe's Internet Bazaar から 2003 年 7 月 3 日 (木) の価格表を取得すれば、今日も同じ価格表が得られます。
また別のデータの種類として、バージョン付きデータがあります。 バージョン付けは、一連の不変データを作成するための方法の 1 つで、一意の識別子を使用します。 Windows NT4 の最新の Service Pack (SP) や、New York Times の最新版について問い合わせることができるのは、バージョン付けが行われているからです。 バージョン付けに使用される識別子には 2 つの種類があります。 1 つはバージョンに依存する識別子、もう 1 つはバージョンに依存しない識別子です。
バージョンに依存する識別子では、目的のバージョンが識別子の一部として含まれます。 この識別子によって、常に同じ不変のビット パターンが取得されます。 一方、バージョンに依存しない識別子には、目的のバージョンが含まれていません。 その結果、バージョンに依存しない識別子を基のデータへと解決するプロセスには、次の 2 つのステップが含まれることになります。
- バージョンに依存しない識別子をバージョンに依存する識別子にマップします。
- そのバージョンの不変のビット パターンを取得します。
このステップを現実の世界の例で見てみましょう。 新聞売り場に New York Times の最新版を買いに来た客がいるとします。 この行動によって、必要なのが今日の新聞かそれとも昨日の新聞かは既に決定されています。 "今日の新聞" というバージョンに依存しない識別子によって、この客は 2004 年 7 月 20 日の新聞 (今日の新聞) を買うことになります。結局、バージョンに依存しない識別子では、要求のたびに同じ回答が得られるわけではありません。 たとえば、次の日にまったく同じことが行われた場合、この客が受け取る新聞は、2004 年 7 月 20 日ではなく 2004 年 7 月 21 日の新聞になります。
メッセージの不変性
ネットワークを通じてやり取りされるすべてのメッセージは、途中で失われて再送信される可能性があります。 送信されたすべてのメッセージは、0 回以上配信されることが保証されています。 このため、以下のケースを考慮に入れる必要があります。
- ネットワークでメッセージが失われた。
- ネットワークでメッセージが再送信された。
- 再送信されたメッセージが実際には配信されていた。
再送信されるメッセージが、何回送信されようと変更されないままであることが重要です。そうでないと、多くの混乱や問題を引き起こすことになります。 したがって、すべてのメッセージは不変である必要があります。
ネットワークを通じてやり取りされるメッセージについては、この他にも考慮すべき問題があります。 通し番号と再試行を用いた信頼性の高いメッセージング フレームワークがないと、エンド アプリケーションでメッセージの重複が発生する可能性があります。 さらに、メッセージング フレームワークとエンドポイントの存続期間にも注意が必要です。 たとえば、完了までに数週間も数か月もかかる長期の作業があるとします。 この場合、TCP/IP で重複を取り除くことができるとは限りません。 というのも、システムがクラッシュして再起動すると、別の TCP 接続が確立されるため、重複するメッセージが送信される可能性があるからです。 再送信されるメッセージによって混乱が生じないように、不変のメッセージを使用して常に同じビットが返されるようにするのが得策です。
図 8. メッセージの不変性
キャッシュするかどうかの問題
一般に、キャッシュについてのほとんどの議論は、キャッシュを使用することに対する警告で終わります。 しかし、この場合は違います。 不変データをキャッシュすることに、少しも問題はありません。要求されるたびに同じデータが返されることが保証されるので、かえって推奨されるほどです。 この場合にはエラーが発生する可能性もありません。 結果として、キャッシュを無効にする必要はありません。 ただし、不変ではないデータをキャッシュするのは、異常を引き起こす可能性があるので危険です。
バージョン付きデータについても、それぞれのバージョンは不変であるため、キャッシュしても問題ありません。 バージョンに依存する識別子を含むキャッシュでは、キャッシュから返されるデータについての混乱もありません。 バージョンに依存する識別子によって、毎回同じビットが得られます。
メモ バージョンに依存しない識別子で参照されるデータをキャッシュすることは推奨されません。 この場合は、結果を予測できなくなります。
正規化と不変データ
データベース スキーマの設計にあたっては、正規化を考慮する必要があります。 正規化によって各データ項目が 1 つの場所にあることが保証されるため、更新の際に問題が生じるのを防ぐことができます。 このことは、従業員とマネージャのデータベースについての古典的な例に示されています。 一般にこのデータベースでは、各従業員の行にマネージャの電話番号が含まれています。 しかし、このようにマネージャの電話番号が多数の場所にあると、それを更新するときに問題が生じます。
図 9. 非正規化の問題
不変データについては、非正規化を許可しても実用上問題ありません。 たとえば電子メール メッセージは、いったんサービスから送信されると変更できないため、非正規化してもかまいません。 また、メッセージがサービス間で送信され、サービスのビジネス ロジックによって解釈される場合、結合を行うことが困難になる可能性があります。 このため、不変のメッセージには多くの場合、非正規化された情報が含まれています。
不変のスキーマ
メッセージの送信や再送信が可能であっても、送信側と受信側のいずれかがメッセージを理解できないと、結局は何も行われません。 したがって、すべてのメッセージには共通のスキーマが必要です。 使用されるスキーマは、一般にメタデータと呼ばれます。 万一このメタデータが変更されると、混乱が生じます。 したがって、使用されるスキーマが常に知られているようにするか、メッセージを処理するときに見つけられるようにする必要があります。
データの安定性
サービスの境界にまたがってデータの不変性を確保することにより、多くの問題を取り除くことができます。しかし、それでもメッセージが理解される保証はありません。 たとえば、"ブッシュ大統領" という発言の意味は、2003 年と 1990 年では異なります。これが 2 人の異なる人物を指していることが理解されないと、メッセージが誤解されることになります。
そこで導入されるのが、時間や場所が変わっても解釈があいまいにならない、安定したデータという概念です。 この概念は、変化しない値を作ることにつながります。 たとえば、ほとんどの企業は顧客 ID や SKU 番号を再利用しません。 これらの値は、かつての意味で解釈されないという保証がないため、永久的に割り当てられます。 銀行を例に考えてみましょう。 銀行の資料で何年も前の顧客情報が見つかり、その顧客の ID を調べる場合、その ID が別の顧客を指していると不便です。 顧客の ID を再利用しないことによって、その安定性が保たれます。
メモ 現在のデータは安定していないという点にも注意が必要です。 たとえば、クレジット カードの現在の利用状況と言う場合、どの時点の利用状況を指すのかが明確に伝わらないため、この発言の意味は安定していません。
以上をまとめると、配布されるデータは、不変性と安定性の両方を備えている必要があります。 不変データを作成するには、バージョン付けがきわめて有効です。 さらに、データは不変のスキーマを参照している必要もあります。 これらが組み合わされて初めて、場所や時間が変わっても変わることのないメッセージの解釈が可能になります。
データの安定性についての補足
外部に送信されるデータはすべて安定したデータでなければなりません。そうでないと、正当な場所および時間の範囲内で各メッセージの解釈の一貫性を保つことができなくなり、情報が理解される保証がなくなります。 また、サービスの内部のデータで安定性が必要となることもあります。 たとえば、外部に送信されるデータが内部にも保持される場合がこれに当たります。 例として、買い物かごとその中の製品の SKU について考えてみましょう。 SKU は、注文遂行サービスに送られるまで買い物かごサービスに保持されます。 買い物かごサービスで保持されている間、SKU は内部の複数のやり取りで使用されるため、安定している必要があります。
データの場所および時間の有効範囲
データの有効範囲を場所や時間で制限すると、そのデータがいつどこで有効なのかがわかります。 たとえば、"この価格は来週の火曜日まで有効です" というようにデータの有効期限を定める場合は、データの有効範囲を時間で制限することになります。 また、データの有効範囲を場所で制限することもできます。 以下に例を示します。
- この価格は、ワシントン州にお住まいの方のみの限定価格です。
- データは、これら 2 つのサーバーでのみ有効です。
- この情報は、Acme & Sons 社の会計アプリケーションに対してのみ有効です。
すべての有効なデータには、不変性と安定性も確保されていなければなりません。 また、有効なデータが取得された場合には、同じデータが生成され、同じように解釈される必要があります。
場所や時間に関係なく常にデータが有効になるようにする前に、有効範囲を制限した方が有益でないかを検討する必要があります。 制限した方がよいことがわかった場合は、その制約をメッセージに記述します。 結局のところ、サービスの外部に送信されるすべてのデータについて有効範囲を定義した方がよいと言えます。
メッセージでデータを送信するためのルール
次の表は、サービスの境界の外部にメッセージを送信するためのルールをまとめたものです。
表 1. データを送信するためのルール
メッセージを識別できるようにします。 |
|
---|---|
データの不変性を確保します。 |
|
キャッシュを利用します。 |
|
有効範囲を定義します。 |
|
データの安定性を確保します。 |
|
外部のデータ: 参照データ
参照データとは
参照データとは、サービスの境界にまたがって発行される情報です。 参照データの各コレクションごとに、それを作成し、発行し、定期的に他のサービスに送信するサービスが 1 つずつあります。 参照データには、大きく分けて 3 つの利用法があります。 すなわち、オペランド、過去の成果物、共有されたデータ コレクションの 3 つです。 この区別は必ずしも厳密ではなく、それぞれが重なり合う場合もあります。
オペランドとオペレータ
オペランドは、処理のために送信されるオペレータ要求を作成するための重要な情報 (パラメータやオプションなど) を追加します。 以下はオペランドの例です。
- 注文を行う顧客の顧客 ID
- 注文される部品の部品番号
- 注文の出荷予定日と合意価格
オペランドのデータは参照データとして発行されます。 一般に参照データは、必要に応じてさまざまなスケジュールで送信されます。 たとえば、次のような例が考えられます。
- 顧客データベースがスナップショットとして毎日送信される。
- 部品カタログが毎週更新される。
- 価格表が毎日更新される。
権限のあるサービスによってバージョン付きの参照データが発行されることで、パートナー サービスでは、そのときどきで適切なオペランドを得ることができます。これにより、情報の正確さが保証されます。 オペレータ要求が処理される際には、オペランドがバージョン付きの参照データから派生したことが理解されている必要があります。 これは、たとえば、デパートの注文が秋冬号のカタログに基づくものであることを指定するのと同じことです。
過去の成果物
過去の成果物も参照データの一種です。 過去の成果物の目的は、過去の情報を送信側サービス内に記録することです。 関連するサービスでは、過去の成果物を受け取り、それを使って他のビジネス操作を実行します。 過去の成果物の例を以下に示します。
- 四半期ごとの販売成績
- 毎月の銀行取引明細書
- 毎月の請求書
毎月の請求書についてはさらなる説明が必要です。 毎月の請求書には、前の月の活動に関する過去の成果物が含まれているだけでなく、顧客に支払いを要求するという働きもあります。 この要求は、ビジネス機能を定義しています。 したがって、毎月の請求書はオペレータとしても機能します。
過去の成果物の使用には、さまざまなプライバシーの問題が伴います。 しかし、過去の成果物はほとんどの場合、信頼関係で結ばれた密接に関連するサービスの間でのみ共有されるか、見られても問題ない相手に対して見られても問題ないデータのみが送られます。 たとえば、四半期ごとの販売成績は、信頼関係で結ばれた密接に関連するサービスの例です。 これらの販売成績は、販売支援サービスによって発行され、経理部のサービスに送信されます。 その後、在庫状況の集計が経理に渡されます。 一方、顧客に送られる銀行の取引明細書や電話代の請求書は、特定の相手に対してのみ送信される過去の成果物の例となります。
図 10. 過去の成果物の発行
共有されたコレクション
参照データは、企業全体または複数の企業の間で同じデータ コレクションを共有することがあります。 このデータ コレクションは、企業全体でアクセスされるようになった後も、引き続き更新および変更できます。 通常は、特定のサービスがこの情報を所有し、システム全体でのデータの更新や新しいバージョンの配布に対して責任を負います。 共有されたデータ コレクションの例を以下に示します。
- 顧客データベース - 企業の顧客に関するすべての関連情報が含まれています。
- 従業員データベース - 企業の全従業員に関する情報が含まれています。
- 部品データベースと価格表 - 部品の名前、SKU、および特性が含まれています。 また、さまざまな SKU の価格や、顧客に対する値引きの方針も含まれています。
ここで、企業全体に配布されるバージョンはそのデータの最新バージョンではない、という点に注意する必要があります。 一般に、疎結合の分散システムにおいては、最新の情報を全体に知らしめることは不可能です。 結果として、データを利用する側では、最近のバージョンで満足せざるを得ません。最新の情報を把握できるのは、権限のあるサービスだけです。 仮に、権限のあるサービスがより新しい情報への要求に応えようとしても、要求した側がそれを受け取るときには既にデータが変更されている可能性があります。 パートナー サービスがその情報を見る時点では、それが最新のコピーであることを権限のあるサービスが保証することはできません。
共有されたデータ コレクションは広く使用されていますが、ほとんどの企業にとって大きな問題となっています。 顧客のデータについてどの値を正しいとするかは、アプリケーションによって異なります。 たとえば、何が顧客を構成するのかについての相違や、 顧客を表現するために必要なデータの相違があります。 さらに、顧客を表現する特定のデータ項目の表現が、さまざまなアプリケーションの間で意味的に統一されていないという問題もあります。 その一方で、こうした不統一を整理しようという動きもあります。 とはいえそれは、ネコの群れを統制しようとするようなものです。
一般には、権限のあるソースを作成することでこの問題に対処します。権限のあるソースは、共有された各データ コレクションの状態を管理し、要求に応じてその時点で最新のバージョンを配布します。 たとえば、さまざまなアプリケーションが顧客管理サービスから共有データの記述を受け取るようになったとします。 このデータを整理するために、各顧客のスキーマに対して、企業全体で共通の標準フィールドと、特定のアプリケーションのみが使用する拡張フィールドを含めます。 しかしそれでも、企業全体にわたってデータを完全に整理することは不可能です。 また、一部の関係者によって独自の拡張フィールドが使用される場合は、それも権限のあるソースで管理する必要があります。 このこともまた問題になります。
共有データの変更の要求
権限のあるサービス以外のサービスで、共有されたデータ コレクションの内容を変更したい場合もあります。 このような場合は、そのサービスが直接内容を更新することはできないので、データの所有者に要求を送信することになります。 これにより、権限のあるサービスでデータを管理できます。 送信される要求は、サービス間でサービス オペレータとして表されるビジネス操作である必要があります。 オペレータとして実装されるのは、サポートされている (権限のあるサービスからエクスポートされることが望まれる) ビジネス機能だけです。 権限のある所有者がデータの変更を承諾すると、その変更は、共有されたコレクションの所有者のビジネス ロジックによって処理されます。 また、少数の変更を加えるのではなく、共有されたデータ コレクション全体の新しいバージョンがパートナー サービスに送信される場合もあります。 たとえば、顧客データベース全体のコピーをパートナー システムに送信する場合などがこれに当たります。
メモ: 規模の大小に関係なく、行われたすべての変更に注意を払う必要があります。というのも、共有されたデータ コレクションが変更されると、権限のあるサービスが何らかのビジネス操作を実行しなければならなくなるからです。
オプティミスティック同時実行制御について
オプティミスティック同時実行制御では、データを読み取る側がデータに変更を加え、その変更を権限のあるサービスに対して提案します。 読み取る側はその際、権限のあるサービスに元のデータを送り返します。 元のデータに問題がなければ、提案した変更が権限のあるサービスによって実行されます。
このオプティミスティック同時実行制御をサービスの境界で使用すべきだという意見があります。 その場合は、次のことが前提となります。
- 外部のサービスはデータの読み取りを許可されている。 ただし、プライバシーやカプセル化の問題からこれが困難になることもあります。
- データの所有者が外部サービスのビジネス ロジックを信頼している。 結局のところ、書き込むように提案するデータのイメージを作成するためには、外部で何らかのロジックを実行する必要があります。
サービスの境界にまたがる更新は、オプティミスティック同時実行制御とはほとんど関係がありません。 代わりに、それを取り巻くロジックと密接な関係があります。 そこで問題となっているのは、信頼関係と、誰がデータを変更できるのかです。 サービスは基本的に相手を信頼しないため、ローカル データベースに格納されるデータの作成を外部のビジネス ロジックに許可することはありません。 ローカル データベースに格納されるデータを作成できるのは、ローカルのビジネス ロジックのみです。 したがって、パートナー サービスにとっては、送られてきたデータをそのまま変更することはできず、そのデータの所有者に変更を依頼する必要がある、という認識が重要になります。
例: 顧客の住所の更新
上の議論に対しては何度も反例が提示されており、オプティミスティック同時実行制御を使って顧客レコードを管理するべきだと主張されています。 ここでは、なぜサービスの境界でオプティミスティック同時実行制御を使用することが問題なのかを示します。
図 11. 共有されたコレクションの複数のバージョンと更新の要求
販売員が顧客レコードのいくつかのフィールドを直接更新し、その変更を (オプティミスティック同時実行の競合がないことを前提に) 権限のあるサービスに対して "書き込み" として送信することは、最初は問題ないように見えるかもしれません。 しかしこれは、互いに関連する 2 つの理由から問題になります。 第 1 に、データの所有者は、データの変更を制御する権限を他のサービスのビジネス ロジックに譲ろうとはしません。 データの整合性を維持するために、自身のビジネス ロジックで変更を管理しようとします。 第 2 に、フィールドが変更されると、何らかのビジネス操作が必要になる可能性があります。 たとえば住所が変更されると、税金に影響が出たり、担当の販売員が変わったり、出荷された製品を転送する必要が生じる可能性があります。 したがって、ただ顧客レコードのフィールドを変更すればよいという問題ではありません。 要するに、ビジネス機能 ("顧客住所の更新をお願いします" など) を中心とする、権限のあるサービスとのやり取りが不可欠なのです。
バージョン付き参照データの発行
データを発行するサービスでは、参照データの混同を避けるために、まずデータの名前を定義する必要があります。 その後、データが更新されるたびにバージョン番号を追加していきます。 以下は、オペランド、過去の成果物、および共有されたコレクションのバージョン付き参照データの例です。
- オペランド: 2004 年 7 月 19 日 (月) 付けの価格表
- 過去の成果物: Joe の 2 年前の 2 月の銀行取引明細書に対する要求
- 共有されたコレクション: 日付が木曜日でタイムスタンプが午前 10 時の顧客データベース
更新された情報には、データの各コピーを区別できるように必ずバージョンが付けられます。 準備が整ったら、メッセージングやファイル コピーなど、さまざまな方法を使って情報を送信できます。 現在最もよく使用されている方法は FTP です。 結局のところ、情報を送信する方法はそれほど重要ではありません。 重要なのは、オペランド、過去の成果物、および共有されたコレクションがサービス間コンピューティングでどのように機能するのかです。
内部のデータ
これまでは、ネットワーク間のメッセージの送信、データの不変性と安定性の問題、サービス間のデータの発行など、外部のデータに焦点を絞って説明してきました。 以降は、内部のデータに焦点を移します。
データとしてのメッセージ
すべてのサービスはメッセージを受信します。 これらのメッセージには、サービスに機能の実行を依頼するオペレータが含まれています。 この機能は、ビジネス上の指示の場合もあれば、製品の注文の場合もあります。 また、送られてきた参照データを受け取る場合もあります。
サービスは、メッセージを受信すると、それを SQL (Structured Query Language) データベースのデータとして記録およびコミットします。 これにより、そのデータが格納され、取得できるようになります。 次に、受信メッセージを処理済みとしてマークするトランザクションが発生します。 このトランザクションの一部として、後に送信する送信メッセージがローカル データベースのキューに入れられます。 最後に、トランザクション全体がアトミック トランザクションとしてコミットされます。 すべての操作がコミットされる前にトランザクションが中止された場合は、受信メッセージが再びキューに入れられて、トランザクションが再試行されます。 このようにトランザクションが中止される可能性があるため、送信メッセージはトランザクションが処理されるまで送信されません。これにより、メッセージの送信とトランザクションの残りの部分との間にアトミック性が確保されます。 たとえば、メッセージが送信された後にトランザクションが中止されると、トランザクションが失敗したにもかかわらずメッセージが処理されてしまいます。 この場合、トランザクションが完全には元に戻されていないため、トランザクションのアトミック性が損なわれることになります。
SQL データベースに受信メッセージを格納することには、トランザクションのサポートのほかに、ビジネス上のメリットもあります。 たとえば、監査やビジネス インテリジェンスの分析など、さまざまな目的でメッセージの内容を簡単に取得できます。 このほか、進行中の作業を SQL クエリで管理および監視できるというメリットもあります。
サービスの内部のデータの種類
サービスの内部には、次の 3 種類のデータがあります。
表 2. サービスの内部のデータ
他のサービスからの参照データ |
|
メッセージ (オペレータと応答) |
|
サービス専用データ |
|
以降のセクションでは、上の表に示した 3 種類のデータの特性と使用方法について検討します。
サービス専用データ
サービス専用データはサービスの内部にあり、サービスのビジネス ロジックによって保護されています。 このデータの内容をそのまま参照したり利用したりできるのは、そのデータを含むサービスだけです。 サービス専用データをサービスの外部から読み取るには、公開するデータを制御しているビジネス ロジックを呼び出すしかありません。
一般にこのデータは、特定の結果 (きわめて具体的な情報) が得られるように大量の処理が施されています。 例として、銀行の ATM について考えてみましょう。 ATM を使用する顧客が、口座管理システムのバック エンド データを意識することはありません。 顧客の目に触れるのは、口座の残高や過去 10 件の取引などの情報のみです。 こうした情報はすべて、銀行のビジネス ロジックによって大量の処理が施されています。 こうしたサービス専用データを外部から変更するには、サービスに対してビジネス操作を送信するしかありません。 たとえば、顧客が現金引き出しなどの取引を行うと銀行のデータが変更されますが、 これは、現金引き出しというビジネス操作を通じて、銀行のバックエンド サービスのサービス専用データが間接的に変更されるためです。
参照データのレプリケーション
通常は、1 つの発行者が多数のサブスクライバに参照データを送信します。 参照データは不変かつバージョン付けされているため、異なるサービス間でのレプリケーションも簡単です。 また、意味があいまいではないため、多数のコピーを簡単に保持できます。
参照データは、サービスにインポートすることもできます。 サービスに読み込まれるときに、処理、再フォーマット、インデックス付けなどが行われる場合もあります。 サービスに格納されたデータは、変更されずに維持されます。 参照データの構文や内部表現がサービスの必要性に合わせて変更されることはあっても、その意味は変わらないため、同じ不変データの 1 つの表現と見なされます。
メモ サブスクライブしているサービスの内部に格納される参照データはレプリカです。 しかし、すべての参照データは不変であるため、データのレプリカとコピーの間に実際の違いはありません。
図 12. 内部のデータのトランザクションでの使用
データ: 過去または未来 (Then) と現在 (Now)
サービスの内部のデータと外部のデータでは、時間的な解釈に重要な違いがあります。 ここでは、サービス指向アーキテクチャの時間のパースペクティブと使い方の違いについて検討します。
現在 (Now) の存在: トランザクションと内部のデータ
トランザクション システムの目的は、アプリケーション開発者が単独でデータベースを操作しているように作業できるようにすることです。 データベースとやり取りする他のすべてのトランザクションが問題のトランザクションより前または後に発生しているように見えることを、直列化可能性と呼びます。
トランザクションは、それが実行されている間、"現在" に存在すると見なすことができます。 直列化可能性によって、アプリケーションの観点から見て別の処理が同時に行われる可能性はありません。 セキュリティの条件さえ満たしていれば、アプリケーションで可能な限り最新の情報を表示して、データベース内のほとんどすべてのデータを調べたり変更したりできます。 このことは、アプリケーションははっきり "現在" に存在している、というパースペクティブにつながります。
サービスの内部でサービスのビジネス ロジックが扱うのは、サービス専用データの最新かつ最大のビューのみです。 ここから、サービスのロジックは、サービスの "現在" とサービス専用データに深く結び付いていると言えます。
過去または未来 (Then) の存在: 外部のデータ
メッセージで送信されるオペレータは、ビジネス機能の実行に対する要求です。 したがって、送信側では、サービスがそのビジネス機能を近い将来に実行することを望んでいることになります。 送信側ノードでトランザクションがコミットされた時点では、要求した操作がまだ行われていないことは明らかですが、それは近い将来に行われます。
ここで、サービス間で送信されるさまざまな種類の参照データと、そのデータの時間的な意味について考えてみましょう。 既に述べたように、参照データは大きく 3 つのカテゴリ (オペランド、過去の成果物、共有されたコレクション) に分類できます。
オペランドは、ビジネス機能のオペレータ要求を作成するためのデータを表します。 デパートのカタログと同様に、オペランドには有効期間があるのが一般的です。 その期間を過ぎると、オペレータの作成に使用されたとしても無効になります。 この期間には現在が含まれると考えられますが、そこで問題となるのが "現在" の即時性でないことは明らかです。 この期間は、"過去または未来" に含まれる範囲なのです。
過去の成果物は、発行する側のサービスの内部で過去に起こったことを表します。 過去の成果物が現在や未来を扱うために使用されることはありません。過去の成果物が扱うのは過去だけです。
共有されたデータ コレクションが扱うのも過去です。 たとえば、権限のあるサービスが企業の顧客の状態のビューを毎日発行するとします。 この場合、パートナー サービスの処理は、昨夜の顧客の状態に基づいて行われることになります。 ここでもまた、パースペクティブは "過去または未来" を扱うものとなります。
サービス: 現在 (Now) と 過去または未来 (Then) の扱い
サービス指向アーキテクチャへの移行における最大の難関の 1 つが、パートナー サービスによって外部から送られてくるデータの "過去または未来" とサービス自体の内部の "現在" の両方を理解しなければならないということを、プログラマに理解させることです。
サービスが提供するビジネス機能の意味によって、この "過去または未来" と "現在" の間の緊張を緩和する必要があります。 サービスによってサポートされる動作をビジネス機能のメッセージ コントラクトで抽象化または緩和することによって、この "過去または未来" と "現在" の違いに対処できます。 これはまさに、企業間の作業で何世代にもわたって行われてきたことです。 たとえば、デパートのカタログには異なる多数の商品が含まれており、カタログに提示されている価格が半年以上にわたって保証されます。 ビジネス ロジックと、サービス コントラクトのインテリジェントな設計によって、この "過去または未来" と "現在" の間の軋轢に対処できます。
データの表現: 内部と外部
本論の残りの部分では、内部と外部のデータの表現に焦点を当てます。 また、XML (Extensible Markup Language)、SQL (Structured Query Language)、およびオブジェクトの 3 つのモデルを比較分析します。 最終的には、サービスの内部のデータとサービスの外部に送信されるデータとの根本的な違いを明らかにします。 また、ある用途における各モデルの長所が別の用途では短所となることも示します。
内部と外部のデータ
データは、内部のデータと外部のデータの 2 種類に大別できます。 外部のデータは、メッセージという形でサービスの境界にまたがって送信されます。また外部のデータには、ビジネス機能と参照データが含まれています。これらは、メッセージの送信側と受信側の両方で理解される必要があります。 外部のデータは常に不変であり、バージョンを付けることもできます。 外部のデータはサービス間でやり取りされるため、複数のバージョンがレプリカとして受信側のサービスに格納されている可能性があります。 一方、内部のデータはサービスの内部に存在し、サービスの外部に送信されることはほとんどありません。 外部に送信される場合は、ビジネス ロジックによって処理される必要があります。 この種のデータは本来サービス専用であり、コードによってカプセル化されています。 次の表は、この 2 種類のデータに関するその他の情報をまとめたものです。
表 3. 内部のデータと外部のデータ
不変である | 正規化が利用される | 安定している | |
---|---|---|---|
外部のデータ | はい | いいえ: 不変である | はい |
内部のデータ | いいえ | はい | 必須ではない |
この表から、外部のデータは常に不変であることがわかります。 このため、正規化の概念は重要ではなくなります。 ただし、不変であるだけでは十分ではありません。外部のデータは、時間や場所が変わっても意味が明確に理解されるように、安定している必要もあります。 データの安定性を確保するためには、バージョンやタイムスタンプを使用できます。 内部のデータについては、安定性は問題になりませんが、安定性を確保することもできます。 たとえば、外部に送信されるデータを参照しているデータには、安定した項目を含めることができます。 内部のデータは必ずしも不変ではないため、更新の際に問題が生じないように正規化する必要があります。
範囲のあるデータ表現と範囲のないデータ表現
ここでは、SQL と XML のデータの表現方法と、その表現のスコープの意味について考察します。
SQL データベースに格納されているすべてのデータは、データベースの範囲内に存在します。 したがって、値に基づく比較が意味を持つのは、値のドメインが同じ場合だけです。 SQL データベースをそのデータベースの外部で解釈することは不可能です。
データベースの変更に使用されるトランザクションのスコープは、データベース内に格納されている関連する値の時間的な範囲を定義します。 たとえば、トランザクションがコミットされて、データのコピーがサービスの外部に送信される場合、そのコピーが使用される前に基の値が変更される可能性があります。 ロックが解除された後に値を解釈すると、意味的な問題が生じることになるため、通常はこれを避けます。
最後に、リレーショナル データにも、厳密に管理されているスキーマがあります。 このスキーマは、トランザクションの中でデータ定義言語 (DDL) によって変更できます。 一般に DDL は、SQL データベースに密接に関連付けられています。 実際、あるトランザクションがコミットされた直後に、次のトランザクションによって、前のトランザクションの意味を成立させていた DDL が変更されることもあります。 この高度な柔軟性を持つ動作は、データベースの範囲内でのみ正しく定義されます。
XML のスキーマはオープンであるため、XML のドキュメントやメッセージには SQL とは違って範囲がありません。 XML のスキーマ定義では、スキーマを独立して作成できます。このため、独自のマークアップ言語を設計したり、他のスキーマの一部を流用することができます。 また、各スキーマは、メタデータの不変のバージョンを表す URI (Universal Resource Identifier) で識別されます。 メッセージが送信されると、そのメタデータの URI によって、そのメッセージを解釈するためのスキーマが明確に指定されます。 このメタデータは、場所や時間が変わっても変わることはありません。
XML と SQL のもう 1 つの違いは、XML では値ではなく参照を使用して情報を接続するということです。 サブツリー間の接続やドキュメント間の接続は、URI として実装される参照によって行われます。 URI として実装された参照は、スキーマ、場所、時間などが変わっても変わることのない、明確なデータ接続メカニズムとなります。
XML の情報は "過去または未来" に存在し、常に過去または未来を表しているため、いつでも明確に解釈できます。 "現在" の概念は、アトミック トランザクションを共有しないシステムの間では困難です。 このようにデータの意味において "過去または未来" を指定できるため、時間や場所の影響を受けない解釈が可能になります。 一方、SQL データベース内の密接な "現在" の中に存在する SQL は、その "現在" および SQL データベース (またはそれに代わるもの) の範囲内でしか正確に理解することはできません。
内部のデータと外部のデータの特性
ここでは、内部のデータと外部のデータについて、さらに詳しく見ていきます。メッセージ データ、参照データ、およびサービス専用データをさまざまな特性について比較することで、この 2 種類のデータをさらに細かく区別します。
表 4. 内部のデータと外部のデータの特性
外部のデータ | 内部のデータ | ||
---|---|---|---|
メッセージ データ | 参照データ | サービス専用データ | |
不変である | はい | はい | いいえ |
相互運用のためのオープンなスキーマが必要 | はい | はい | いいえ |
XML で表現される | はい | はい | いいえ |
カプセル化を使用できる | いいえ | いいえ | はい |
アクセスがカプセル化されている | いいえ | いいえ | 可能 |
変化するスキーマを持つ変化するデータが長期にわたって使用される | いいえ | いいえ: 不変のバージョン | はい |
ビジネス インテリジェンスを利用できる | はい | はい | はい |
SQL データベースに格納される | はい: XML のコピーが SQL データベースに格納される | はい: XML のコピーが SQL データベースに格納される | はい |
メッセージ データと参照データ (どちらも外部のデータ) は、不変である点、オープンなスキーマを持つ点、および XML で最適に表現される点で似ています。 一方、サービス専用データでは、オープンなスキーマによる相互運用の対極にあたるカプセル化が推進されています。 さらに、内部のデータと外部のデータとではスキーマの変更方法も異なります。 たとえば、メッセージ スキーマが変更される際には、スキーマの明確なバージョン付けが行われます。 一方、DDL によってスキーマの現在の状態が変更されると、内部のデータに影響が及ぶ場合もあります。 最後に、受信メッセージと送信メッセージの両方が SQL へと分解されますが、これは、内部にあるか外部にあるかという場所の違いに関係なく、ビジネス インテリジェンスはすべてのデータにとって重要な要素であるためです。 一般に、クエリのために分解される XML の量は、分析が求められる量に基づいて決定されます。 この分解の操作は、XML の拡張性のゆえに、簡単な場合もあれば困難な場合もあります。スキーマにマップされないデータが送られてきた場合には困難になります。
データの種類を区別し、それぞれの機能を把握できたら、次はどの技術を使用すればよいのかを考える必要があります。 次のセクションでは、XML、SQL、およびオブジェクトの 3 つのモデルと、それぞれのデータ表現について検討します。
オブジェクトについて
オブジェクト指向によってソフトウェア開発がいかに促進されるかは広く知られていますが、 オブジェクトは、データを表現する際にも有効です。 オブジェクトの永続性については既に知られており、オブジェクト指向データベースも、ときに期待を裏切られることもありますが、広く普及しています。 また、オブジェクト指向には、データを表現する手段としての利用を促す重要な力があります。
SQL や XML に対するオブジェクトの最大のメリットは、カプセル化を利用できることです。 格納されているデータは、データを使用するユーザーからは見えません。ユーザーから見えるのは、オブジェクトによって提供されるメソッドの動作だけです。 これは、サービスにおいて、スキーマやコントラクトで定義されるメッセージを通じてビジネス機能が公開されるのとよく似ています。 オブジェクトとサービスの根本的な違いは、サービスは参照データとして共有する以外はデータを共有しないという点です。 これは、オブジェクト間の関係に比べてはるかに緩やかな関係です。
それでも、オブジェクトを使用してサービスを実装することは大いに推奨されます。 実際、オブジェクト指向環境のメリットなしにサービスを実装しようとする人はいないでしょう。 オブジェクトを使用して実装したサービスは、すべてのパートナー サービスに対して非透過になります。
3 大技術: XML、SQL、オブジェクト
興味深いことに、各モデルの長所は同時にそのモデルの短所でもあります。 たとえば XML は、スキーマ定義の独立性と参照に基づく階層的な表現との組み合わせや、データの時間的な解釈によって、サービス間の通信に最適なモデルとなっています。 これらの不変のメッセージは、作成するのも異なるサービス間で解釈するのも簡単です。 こうした機能は、XML の範囲を持たない性質に直接由来するものです。 しかし、XML のこうした "外部" のための機能は、内部においては逆に短所となります。 SQL で格納され、"現在" を表現する、正規化されたデータと同じくらい豊かに XML をクエリ、形成、更新できるかは疑問です。 この短所もまた、XML の範囲を持たない性質に直接由来するものです。
SQL は、その特性上、サービスの内部のデータを表現するのに最適なツールとなっています。 この長所は、場所と時間の両方の範囲を持つという SQL の性質に密接に結び付いています。 XML とは違って SQL には強力なクエリ機能があり、 データベースの範囲内のデータを自由に比較できます。 しかし SQL は、その範囲を持つ性質のために、"外部" においては XML ほど強力ではありません。 SQL は、集中化され、緊密に結び付けられた DDL に強く依存しているため、スキーマを独立して定義することはできません。
これら 2 つのモデルには、いずれもカプセル化の機能はありません。 XML ではオープンなスキーマが使用されるため、カプセル化は不可能です。 SQL についてもカプセル化は不可能であり、データの変更は UPDATE DML によってのみ行われるためその必要性もありません。 XML や SQL とは異なり、オブジェクトやコンポーネントはカプセル化を得意としています。 カプセル化では、そもそもデータが見えないため、データの任意の比較を行うことはできません。 したがって、クエリを実行することは不可能です。 また、カプセル化によってスキーマが隠蔽されることになるため、拡張性や定義の独立性も実現できません。
以上をまとめると、XML は、要求、応答、および参照データのサービス間通信の領域で広く利用されています。 XML には、メッセージに必要な機能、拡張性、粒度のすべてが揃っています。 データの格納に関しては、送受信されるメッセージの格納など、数々の優れた機能を備える SQL データベースが優位に立ちます。 監査、整合性、ビジネス インテリジェンスなどに利用することで、その機能をさらに活用できます。 サービスを構築する際には、オブジェクトの使用が推奨されます。オブジェクトには、ソフトウェアの構築を促進するカプセル化の機能があります。
図 13. XML、SQL、オブジェクトの使い分け
なお、この情報は、特定のモデルを推奨しようとするものではありません。 ここでの目的は、それぞれのモデルの長所が同時に短所にもなるという、興味深い事実を示すことにあります。 ただし、3 つのモデルのすべてがサービス指向アーキテクチャになくてはならないということは認識しておいてください。
まとめ
本論では、サービスの内部のデータとサービスの境界の外部に送信されるデータという SOA の難解な部分について取り上げ、 サービス、メッセージ、およびさまざまな技術モデルの役割と関係の議論を通じて、この 2 種類のデータの違いを明らかにしました。
サービスはメッセージによってのみ接続されます。それ以外ではサービスは互いに独立しており、それぞれが個別に機能します。 サービスの間で送信されるメッセージにはビジネス機能が記述されており、操作のパラメータやオプションを表すオペランドが含まれています。 これは、従来の分散システムに比べてはるかに自由度が高く、密接度の低い関係です。 サービスはそれぞれ異なるため、アトミックなデータベース トランザクションがサービスの境界にまたがって共有されることはありません。 結合の決定のあいまいさは、互いにやり取りするサービスのビジネス ロジックによって処理されます。
メッセージもまた、それぞれ異なります。 メッセージは、いったんサービスの境界の外部に出たら、不変でなければなりません。 また、データの安定性に対しても特別な注意が必要です。 この安定性によって、場所や時間が変わってもデータが理解されることが保証されます。
参照データは、メッセージングにおいて重要な役割を担います。 参照データとは、サービスの境界にまたがって発行されるデータです。 オペランド、過去の成果物、共有されたコレクションは、すべて参照データです。 オペランドは、処理のために送信されるオペレータ要求を作成するためのパラメータやオプションです。 過去の成果物は、発行する側のサービスの内部で過去に起こった出来事を表します。 共有されたデータ コレクションは複数のサービスによって使用され、 常に変化し続けます。 その結果、一般にパートナー サービスでは、最近のバージョンのデータにしかアクセスできません。
サービスの内部および外部のデータの表現に関する議論では、SQL、XML、およびオブジェクトのそれぞれにふさわしい場があります。 興味深いことに、これらのモデルでは、ある領域でそれぞれの長所となる性質が別の領域においては短所になります。 データ表現の専門家コミュニティの間で意見の相違が長く続いている理由はここにあります。
最後に、サービスの外部のデータとサービスの内部のデータは異なります。 内部のデータは、"現在" に存在するものとして表されます。 また、通常は特定のサービス専用であり、サービスのコードによってカプセル化されています。 一方、外部のデータは過去に存在しています。 外部のデータはメッセージで渡され、送信側と受信側の両方によって理解されます。
執筆者紹介25 年間にわたってソフトウェア業界に携わってきた Pat Helland は、1994 年以降、Microsoft のアーキテクトとして活躍しています。彼には、データベース、トランザクション処理、分散システム、およびフォールト トレラントなスケーラブル システムに関する 20 年に及ぶ経験があります。 Tandem Computers で TMF (Transaction Monitoring Facility) の設計に携わったほか、 MTS (Microsoft Transaction Server、現在の COM+) を実装および出荷したチームの創設者の 1 人にもなっています。 近年は、疎結合のアプリケーション環境に注目しています。 Pat の連絡先は phelland@microsoft.com です。