トピック

概論ページの先頭へ

この概念の文書では、オブジェクト モデルとリレーショナル データ モデル、永続性フレームワークの概要を説明します。

リレーショナル データベースとオブジェクト指向 ページの先頭へ

リレーショナル データベースとオブジェクト指向は、完全に互換性があるわけではありません。これらは 2 つの異なるビューで世界を表現しています。RDBMS ではデータのみを表示し、オブジェクト指向システムでは振る舞いのみを表示します。一方の観点が他方より優れているということはありません。オブジェクト指向モデルが概してうまく機能するのは、複雑な振る舞いと状態固有の振る舞いを持ちデータが副次的であるシステム、または自然な階層内でのナビゲーションでデータがアクセスされるシステム (たとえば、部品構成表) です。RDBMS モデルが適しているのは、関係が動的またはその場限りである報告のアプリケーションやシステムです。

実際のところ、大量の情報がリレーショナル データベースに格納されており、そのデータにオブジェクト指向アプリケーションがアクセスする必要がある場合は、RDBMS の読み書きができる必要があります。さらに、オブジェクト指向システムは、多くの場合、オブジェクト指向でないシステムとデータを共有する必要があります。したがって、RDBMS を共有メカニズムとして使用することが自然です。

オブジェクト指向とリレーショナル設計は、いくつかの特性が共通します (オブジェクト属性は概念的にエンティティ列と同等) が、根本的な違いがあるので、シームレスな統合は困難です。根本的な違いとは、データ モデルは (列の値によって) データを公開するが、オブジェクト モデルは (public インターフェイスの背後にカプセル化して) データを隠す点です。

リレーショナル データ モデル ページの先頭へ

リレーショナル モデルは、エンティティと関係で構成されます。エンティティは、物理テーブル、または複数のテーブルの論理射影であり、ビューとも呼ばれます。次の図は、「明細」、「注文」、「製品」のテーブル、そしてこれらのテーブルのさまざまな関係を示しています。リレーショナル モデルには次の要素があります。

リレーショナル モデル

エンティティには複数の列があります。各列は名前とタイプによって識別されます。上の図では、「明細」エンティティには「LineItem_Id」(主キー)、「説明」、「Price」、「Quantity」、「Product_Id」、「注文 ID」の列があります (最後の 2 つの列は、「明細」エンティティを「注文」と「製品」のエンティティにリンクする外部キー)。

エンティティにはレコードまたは行があります。各行は、独自の情報のセットを表現し、この情報は通常はオブジェクトの永続データを表現します。

各エンティティには 1 つ以上の主キーがあります。主キーは一意に各レコードを識別します (たとえば、「Id」は「明細」テーブルの主キー)。

関係のサポートはベンダー固有です。この例は、論理モデルと、「製品」と「明細」のテーブル間の関係を示しています。物理モデルでは、通常は、外部キーや主キーの参照を使用して関係が実装されます。1 つのエンティティが別のエンティティに関係する場合、そのエンティティには外部キーである列が含まれます。外部キーの列には、エンティティ内の特定のレコードを、関係するエンティティに関係付けできるデータが含まれます。

関係は多重度を持ちます (多重度は基数とも呼ばれます)。一般的な基数は、1 対 1 (1:1)、1 対多 (1:m)、多対 1 (m:1)、多対多 (m:n) です。この例では、「明細」は「製品」と 1:1 の関係を持ち、「製品」は「明細」と 0:m の関係を持ちます。

オブジェクト モデルページの先頭へ

オブジェクト モデルに含まれるものの 1 つにクラスがあります (オブジェクト モデルについて詳しくは、参考資料 [UML01] を参照)。クラスは、オブジェクトのセット (オブジェクト インスタンスとも呼ばれる) の構造と振る舞いを定義します。この構造は、属性 (データの値) と関連 (クラス間の関係) として表現されます。次の図は、クラスの属性 (データ) のみを表示する単純なクラス図を示しています。

オブジェクト モデル (クラス図)

「注文」には、番号 (「Order Number」)、1 つ以上の (1..*) 「明細」との関連があります。各「明細」には数量 (注文された数量) があります。

オブジェクト モデルは継承をサポートします。クラスはデータと振る舞いを別のクラスから継承できます (たとえば、「ソフトウェア製品」と「ハードウェア製品」の製品は、属性とメソッドを「製品」クラスから継承します)。

永続性フレームワーク ページの先頭へ

ビジネス アプリケーションの大部分は、リレーショナル技術を物理的なデータ ストアとして利用します。オブジェクト指向アプリケーションの開発者が直面している難題は、リレーショナル データベースの分離とカプセル化を十分に行うことで、データ モデルの変更によってオブジェクト モデルが「破壊」されず、オブジェクト モデルの変更でデータ モデルが「破壊」されないようにすることです。アプリケーションがリレーショナル データに直接アクセスできる解決法は多数存在します。難しい点は、オブジェクト モデルとデータ モデルの間でシームレスな統合を実現することにあります。

データベースのアプリケーション プログラミング インターフェイス (API) には、標準的なもの (たとえば、Microsoft の Open Data Base Connectivity (ODBC) API) と、独自のもの (特定のデータベースへのネイティブのバインディング) があります。API は、データ操作言語 (DML) のパス スルー サービスを提供します。このサービスを使用すると、アプリケーションが生のリレーショナル データにアクセスできます。オブジェクト指向アプリケーションでは、データをアプリケーションで使用する前に、オブジェクトリレーショナル変換をしなければなりません。それには、生のデータベース API の結果をアプリケーション オブジェクトに変換するために、かなりの量のアプリケーション コードが必要です。オブジェクトリレーショナル フレームワークの目的は、物理的なデータ ストアを包括的にカプセル化すること、そして適切なオブジェクト変換サービスを提供することです。

永続性フレームワークの目的

アプリケーション開発者は、オブジェクト指向アプリケーション内のリレーショナル データベースのアクセスの実装に、作業時間の 30% 以上を費やしています。オブジェクトリレーショナル インターフェイスが正しく実装されない場合、この投資が失われます。オブジェクトリレーショナル フレームワークを実装すると、この失われる投資を獲得できます。オブジェクトリレーショナル フレームワークは、以降のアプリケーションで再利用できるので、オブジェクトリレーショナルの実装のコストが総実装コストの 10% 未満まで減少します。どのシステムでも、実装時に検討すべき最も重要なコストは保守です。システムのライフサイクル全体での総コストの 60% 以上は、保守コストです。不適切に実装されたオブジェクトリレーショナル システムの保守は、技術とコストの両面で悪夢です。

オブジェクトリレーショナル フレームワークに必須の特性 ページの先頭へ

  • 性能: オブジェクトからデータへの分解と、データからオブジェクトへの組み立てについて、慎重に検討しなければなりません。データのスループットが高く重大なシステムでは、これが不適切に設計されたアクセス レイヤのアキレス腱になりがちです。
  • 設計の妥協の最小化: リレーショナル データベースを利用するシステムを構築したオブジェクト技術者によくあるパターンは、リレーショナル システムへの格納を容易にするようにオブジェクト モデルを調整すること、そしてオブジェクトの格納を容易にするようにリレーショナル モデルを変更することです。微調整が必要なことも珍しくありませんが、優れた設計のアクセス レイヤは、オブジェクト モデルとリレーショナル モデルの両方の設計の劣化を最小限にします。
  • 拡張性: アクセス レイヤは、アプリケーション開発者がフレームワークを拡張できるようにするホワイトボックス フレームワークであり、特定の機能がフレームワーク内で必要とされる場合に使用されます。通常、アクセス レイヤは、拡張しなくてもアプリケーションのデータ記憶領域の要求の 65 ~ 85% をサポートします。アクセス レイヤが拡張可能なフレームワークとして設計されていない場合、アプリケーションのデータ記憶領域の要求の残り 35 ~ 15% を実現することは、非常に困難でコストがかかる可能性があります。
  • 文書化: アクセス レイヤは、ブラックボックス コンポーネントとホワイトボックス フレームワークの両方になります。ブラックボックス コンポーネントの API は明確に定義し、明確に文書化し、容易に理解されなければなりません。前に示したように、アクセス レイヤは拡張できるように設計されます。拡張可能なフレームワークは、完全に文書化しなければなりません。サブクラス化されることが想定されるクラスを識別しなければなりません。関連する各クラスのプロトコルの特性を指定しなければなりません (たとえば、public、private、protected、final など)。さらに、アクセス レイヤ フレームワークの設計のかなりの部分を、公開、文書化して拡張を容易にしなければなりません。
  • 共通オブジェクトリレーショナル マッピングのサポート: アクセス レイヤは、拡張を必要とせずに、いくつかの基本的なオブジェクトリレーショナル マッピングのサポートを提供する必要があります。これらのオブジェクトリレーショナル マッピングについて詳しくは、本書の次の項で説明します。
  • 永続インターフェイス: オブジェクト指向アプリケーションでは、オブジェクト アプリケーションのビジネス モデルは、問題ドメインのセマンティクスの知識を獲得します。開発者がオブジェクトの操作と相互作用をする際に、データの格納と取り出しの詳細をあまり気にせずに済むようにする必要があります。明確に定義された永続インターフェイス (save、delete、find) をアプリケーション開発者に提供する必要があります。

共通オブジェクトリレーショナル サービス ページの先頭へ

オブジェクトリレーショナル アプリケーションでは共通のパターンが現れます。これまで何度も隔たりを埋めてきた IT の専門家たちは、成功するオブジェクトリレーショナル アプリケーションが示す特定の構造と振る舞いを理解し認識し始めています。こうした構造と振る舞いは、高レベルの CORBA サービスの仕様によって形式化されてきました (この仕様は COM/DCOM ベースのシステムに同じように適切に適用されます)。

オブジェクトリレーショナル マッピングの検討のために適用可能で役立つ CORBA サービスの仕様は、次のとおりです。

以降では、これらのカテゴリ別に共通オブジェクトリレーショナル サービスを説明します。詳しくは、適切な CORBA の仕様書を参照してください。

永続性 ページの先頭へ

永続性は、オブジェクトが不連続のセッション間で状態を保持するためにどのように副次的な記憶媒体を利用するかを説明するために使用される用語です。永続性は、ユーザーが 1 つのセッションでオブジェクトを保存し、後のセッションでこのオブジェクトにアクセスできるようにします。このオブジェクトが連続してアクセスされると、その状態 (たとえば属性) は、直前のセッションとまったく同じになります。マルチユーザー システムでは、そのようにならないことがあります。なぜなら、同じオブジェクトにほかのユーザーがアクセスして変更する場合があるからです。永続性は、ここで説明するその他のサービスと相互に関連しています。関係、並行性、およびその他の事項の検討は意図的です (そして CORBA のサービスの分解と一貫しています)。

永続性によって提供される特定のサービスの例としては、次のものがあります。

  • データ ソースの接続管理: オブジェクトリレーショナル アプリケーションは、物理的なデータ ソースへの接続を開始しなければなりません。リレーショナル データベース システムでは、通常はサーバーとデータベースの識別が必要です。接続管理の詳細は、データベース ベンダーに固有の傾向があり、それに応じて柔軟にフレームワークを設計しなければなりません。
  • オブジェクトの取り出し: オブジェクトをデータベースから復元すると、データがデータベースから取り出され、オブジェクトに変換されます。このプロセスでは、データ ソースから取り出されたデータベース固有の構造からデータを抽出し、データベース タイプから適切なオブジェクト タイプかクラスまたはその両方へとデータを結合し、適切なオブジェクトを作成し、具体的なオブジェクト属性を設定する必要があります。
  • オブジェクトの格納: オブジェクトの格納のプロセスは、オブジェクトの取り出しを反映します。適切な属性の値がオブジェクトから抽出され、この属性値 (SQL 文字列、ストアド プロシージャ、特殊なリモート プロシージャ コールなど) を使用してデータベース固有の構造が作成され、この構造がデータベースに登録されます。
  • オブジェクトの削除: システムの中からオブジェクトを削除する場合は、関連するデータをリレーショナル データベースから削除しなければなりません。オブジェクトを削除するには、該当する情報をそのオブジェクトから抽出し、削除の要求 (SQL 文字列、ストアド プロシージャ、特殊なリモート プロシージャ コールなど) を作成し、この要求をデータベースに登録する必要があります。(Smalltalk や Java などの) 一部の言語では、明示的な削除がサポートされていず、ガーベッジ コレクションという戦略がサポートされています。これらの言語をサポートする永続性フレームワークは、アプリケーションが参照しなくなったデータをデータベースから削除する代替の方法を提供しなければなりません。一般的な方法の 1 つは、オブジェクトがほかのオブジェクトから参照される回数の参照カウントをデータベースが保持する方法です。参照カウントがゼロになったオブジェクトは、ほかのオブジェクトから参照されていず、削除が可能かもしれません。参照カウントがゼロのオブジェクトの削除が可能かもしれないとする理由は、参照されなくなったオブジェクトでも、クエリーの対象になるかもしれないからです。オブジェクトの削除をどの時点で許可するかについてのデータベース全体のポリシーが依然として必要です。

クエリー ページの先頭へ

永続オブジェクトの格納は、特定のオブジェクトの検索と取り出しのメカニズムがなければほとんど役立ちません。クエリー機能を使用すると、アプリケーションでさまざまな基準に基づいたオブジェクトの問い合わせと取り出しができます。オブジェクトリレーショナル マッピング フレームワークが提供する基本的なクエリー操作は、find と find unique です。find unique 操作は、特定のオブジェクトを取り出し、find はクエリー基準に基づいてオブジェクトのコレクションを返します。

データ ストアのクエリー機能には、さまざまな種類があります。単純なファイルベースのデータ ストアは、固定された自社作成のクエリー操作を実装できるのに対し、リレーショナル システムは、柔軟なデータ操作言語を提供します。オブジェクトリレーショナル マッピング フレームワークは、リレーショナル クエリー モデルを拡張し、データ中心ではなくオブジェクト中心にします。リレーショナル クエリーの柔軟性とベンダー固有の拡張 (ストアド プロシージャなど) を利用するために、パス スルー メカニズムも実装されます。

データベースに基づいたクエリー メカニズムとオブジェクト パラダイムの間には潜在的な矛盾があります。つまり、データベース クエリー メカニズムはテーブル内の属性 (列) のによって駆動されます。対応するオブジェクトでは、カプセル化の原則のために属性の値を見ることができません。クラスの操作によってカプセル化されるからです。カプセル化を行う理由は、アプリケーションの変更を容易にすることです。クラスの内部構造を変更するときに、そのクラスの一般から見える操作が変更されない限り、依存するクラスを気にせずに済みます。データベースに基づいたクエリー メカニズムは、クラスの内部表現に依存し、効果的にカプセル化を破壊します。フレームワークにとっての難題は、クエリーによってアプリケーションが変更時にもろくならないようにすることです。

トランザクション ページの先頭へ

トランザクションをサポートすると、アプリケーション開発者が作業の最小単位を定義できます。この意味するところは、データベースの用語では、システムが変更のセットをデータベースに適用できなければならない、または変更が 1 つも適用されないと保証しなければならない、ということです。1 つのトランザクション内のすべての操作の実行が成功するか、トランザクション全体が失敗するかのどちらかです。オブジェクトリレーショナル フレームワークは、最低でもリレーショナル データベースのようなコミット / ロールバックのトランザクション機能を提供する必要があります。マルチユーザー環境でのオブジェクトリレーショナル フレームワークの設計では、多数の難題が生じる可能性があり、慎重に検討する必要があります。

永続性フレームワークが提供する機能のほかに、アプリケーションがエラーの処理方法を理解しなければなりません。トランザクションが失敗するか中断されると、システムはそのトランザクションの状態を、以前の安定した状態に復元できなければならず、通常はそのためにデータベースから以前の状態情報を読み取ります。したがって、永続性フレームワークとエラー処理フレームワークの間には綿密な相互作用があります。

並行性 ページの先頭へ

マルチユーザーのオブジェクト指向システムでは、オブジェクトへの並行アクセスを制御しなければなりません。1 つのオブジェクトが多数のユーザーから同時にアクセスされるときに、システムは、永続記憶領域内のオブジェクトの変更が予測と制御が可能な方法で発生するメカニズムを提供しなければなりません。オブジェクトリレーショナル フレームワークは、悲観的か楽観的またはその両方の並行性コントロールを実装できます。

  • 悲観的並行性コントロールでは、オブジェクトがデータ ストアから取り出されるときに、アプリケーション開発者が自分の意図 (たとえば、読み取り専用、書き込みロックなど) を指定する必要があります。オブジェクトがロックされる場合、ほかのユーザーがオブジェクトにアクセスするときに妨害し、ロックが放棄されるのを待つ可能性があります。悲観的並行性の使用と実装は慎重に行う必要があります。なぜなら、デッドロックが発生する可能性があるからです。
  • 楽観的並行性コントロールでは、同じオブジェクトが同時にアクセスされることはまずないと想定します。変更がデータベースに保存されるときに、並行性の競合が検出されます。通常は、オブジェクトが取り出しの後で別のユーザーに変更されると、変更操作の失敗を示すエラーがアプリケーションに返されます。エラーの検出と処理はアプリケーションの責務です。したがって、フレームワークが、オブジェクトの並行する値をキャッシュし、データベースと比較する必要があります。並行性の競合がほとんどなければ、楽観的並行性のほうが低コストですが、競合がかなり多ければ高コストになります (なぜなら、競合が発生したときに作業をやり直す必要があるからです)。

共有データを使用するすべてのアプリケーションが、同じ並行性戦略を使用しなければなりません。同じ共有データ内で楽観的と悲観的の並行性コントロールを混在させることはできません。混在させると、破損の可能性があります。並行性戦略を一貫させるには、永続性フレームワークによって処理することが最適です。

関係 ページの先頭へ

オブジェクトは、ほかのオブジェクトとの関係を持っています。「注文」オブジェクトには多数の「明細」オブジェクトがあります。「Book」オブジェクトには多数の「Chapter」オブジェクトがあります。「Employee」オブジェクトが属す「Company」オブジェクトは 1 つだけです。リレーショナル システムでは、エンティティ間の関係は外部キー / 主キーの参照を使用して実装されます。オブジェクト指向システムでは、関係は通常は属性によって明示的に実装されます。「注文」オブジェクトに「明細」がある場合、「注文」には明細という名前の属性が含まれます。「注文」の明細属性には、多数の「明細」オブジェクトが含まれます。

オブジェクトリレーショナル フレームワークの関係の側面は、永続性、トランザクション、クエリー サービスと相互に依存しています。オブジェクトの格納、取り出し、トランザクション処理、クエリーを行うときは、関係するオブジェクトについて次のような考慮をしなければなりません。

  • オブジェクトを取り出すときに、関連するオブジェクトも取り出すべきか。きわめて単純に考えればそうすべきですが、そうすると、関連するオブジェクトが不要なときに非常に高コストになります。優れたフレームワークを使用すると、戦略を混在できます。
  • オブジェクトを格納するときに、関連するオブジェクトが変更された場合に、関連するオブジェクトも格納すべきか。この場合も、状況に応じて答が異なります。

共通オブジェクトリレーショナル サービスを別個に検討することは概念的に有利ですが、オブジェクトリレーショナル フレームワークの実装は共依存になります。個別の組織間だけではなく、同じデータを共有するすべてのアプリケーションで一貫して、このサービスを実装しなければなりません。フレームワークは、これを実現する唯一の経済的な方法です。



Rational Unified Process   2003.06.15