0

ユーザーストーリー:

アプリのユーザーがロードトリップを作成します。Aroadtripは一連の興味深い目的地です。それぞれdestinationに、そこにいる間に見るべき活動や光景に関する詳細がいくつかあります。このようにして、ユーザーは 2 つの遠征を定義します。各旅行にはいくつかの固有の目的地といくつかの共通の目的地があります。たとえば、両方の旅行に The Smithsonian が含まれます。アプリはすべての更新をメモリに保持し、ユーザーが [保存] をクリックしたときにのみデータベースにコミットします。ユーザーは両方の旅行を積極的に更新し、自由に切り替えることができます。アプリのポイントでは、スミソニアンの目的地を扱っていますが、目的地から目的地を含むロードトリップまでオブジェクト階層を上に移動する必要がある場合があります。問題は、目的地が 2 回の遠征に参加することです。

RoadTrip1
 |
 +-Destination1
 +-Destination2
 +-Destination3
 +-Smithsonian (A) //Navigate up to RoadTrip1

RoadTrip2
 |
 +-Destination4
 +-Smithsonian (B) //Navigate up to RoadTrip2
 +-Destination5

宛先オブジェクトのコピーが 1 つだけであることを保証しながら、後方へのナビゲーションを可能にするために使用できる優れた設計パターンまたはデータ構造は何ですか?

要件:

  1. モデルは多対多の関係に関係しています。
  2. すべてのモデルをメモリ内で 1 回だけ表現します (アイデンティティ マップ)。
  3. データ構造は簡単にナビゲートできる必要があります。親から子にナビゲートできるだけでなく、子から、子が最初にフェッチされた親にナビゲートすることもできます。
  4. データ モデルに追加のスキーマを導入することは避けたいと考えています。

これまでの私の最善のアイデアは、各宛先オブジェクトをコンテキスト オブジェクトでラップすることです (リンクされたリストがノードをラップする方法と同様)。コンテキスト オブジェクトは、最初にフェッチされた親へのポインターを維持します。各宛先は常にそのラッパーを介して処理します。これは Proxy パターンか Decorator パターンのどちらかだと思います (私は Proxy の方に傾いています)。(これは本質的に、jQuery オブジェクトが多くの要素を包含し、複数の jQuery オブジェクトが同じ要素への参照を共有する方法と同じ考え方ではないでしょうか?)

「現在のロードトリップ」コンテキスト変数を維持することを検討し、それを目的地からそれを含むロードトリップまでナビゲートするために使用しました。これは、実際の「フェッチ コンテキスト」ほど信頼性が高くありません。実際、それはまったく異なるタックであり、私はそれが好きかどうかわかりません.

ActiveRecord で同じ問題が発生したことを覚えています (ただし、使用してからしばらく経ちます)。AR では、RoadTrip1 から始めてその目的地をフェッチした場合、目的地からロード トリップまで (ある種のフェッチ コンテキストを介して) うまくナビゲートできませんでした。代わりに、私は両方の両親 (遠征) を検討する必要があり、どうやってそこにたどり着いたかについての指標はありません。右?

他の人は以前にこの問題に遭遇したことがありますか? つまり、多くの親が後方ナビゲーションを混乱させている場所で後方にナビゲートしたいということですか? 「私はどちらの親からここに来たのですか?」と尋ねたことはありますか? あなたはそれにどう答えましたか。

4

2 に答える 2

0

プロキシ パターンを使用した後のソリューションを作成することができました。私が本当に欲しかったのは、「コンテキストを取得する」という概念でした。最初にモデルを取得した親 (複数の親を持つ子) を知りたいと思いました。

問題を解決するための鍵は、取得コンテキストを維持することは、モデルではなくクエリ オブジェクトの責任であると認識することでした。

var activity = roadtrip.destinations().all().activities().first();

roadtripモデルから始めて、destinations関数を呼び出します。この関数はクエリ オブジェクトを返します。allこのクエリ オブジェクトは、レイジーで、firsteach、 などを呼び出すまで実際にはレコードを返さないという点で、Rails の Arel 実装と設計が似ています。クエリ オブジェクトには、その親であるモデルcontextを指す変数があります。roadtrip

この呼び出しは、呼び出し元のクエリを指すallコレクション オブジェクトを返します。コレクション内の各アイテムは、基礎となる各モデルをラップcontextするプロキシ (a ) です。プロキシは、そのコレクションへの参照を維持します。このプロキシを実現する最も簡単な方法は次のとおりです。queried itemdestination

var proxied_destination = Object.create(destination);

このようにcontextして、オリジナルに影響を与えずに をプロキシに割り当てることができます。

proxied_destination.context = collection;

これにより、「マスター」モデルを変更せずにアイデンティティ マッピングを行うことができます。モデルは複数の結果セットに参加でき (必要な数のクエリを実行できます)、私のシナリオでは 1 つのコンテキスト (親) のみを想定しているため、モデルがそのコレクションへの直接参照を維持している場合、これは不可能です。

これを呼び出しactivitiesて、コンテキストがプロキシされた別のクエリ オブジェクトを提供しますdestination。コレクションを呼び出しfirstて取得するのではなくactivity、アクティビティ クエリ オブジェクトを指すコンテキストを持つプロキシを取得します。

そのため、プロキシを使用すると、オブジェクト階層を上に向けて「登る」ことができますが、その階層に気付かず、複数のコレクション (結果セット) に簡単に参加できる ID マップ モデルを維持できます。

于 2011-09-19T14:38:58.813 に答える
0

Roadtrip、Destination、Place の 3 つのクラスが必要です。したがって、目的地 A と B は、両方とも同じ場所を参照する 2 つの異なるオブジェクトです。

于 2011-09-16T15:16:21.610 に答える