1

説明するのが簡単ではないシナリオがありますが、それは非常に一般的な問題であると確信しています。私は問題を説明するために最善を尽くします。

調査を作成できるSurveyアプリケーションがあるとします。各調査には独自の構造があります(質問が含まれている、質問がグループ化されて順序付けられているなど)。これらの調査は管理者によって管理され、マスター調査テンプレートと呼ばれます。これで、ユーザーはこれらのマスターサーベイのいずれかを選択し、カスタマイズを行って、一部の人に対してサーベイを実行できます。

したがって、基本的に、すべて同じ構造(コレクション、プロパティなど)を共有する調査がありますが、データは異なる場合があります。

DBをどのようにモデル化しますか?

私の考えは、すべてを1つのテーブルに格納し、実行されたテンプレートからテンプレートを分離する列を作成することです。

tbl_Survey (id, name, conducted_on)

クラスをどのようにモデル化しますか?

私の考えは次のとおりです。

Survey {
  Name
  Questions
}

ConductedSurvey : Survey {
  //gets the master according to the name
  GetMaster()
}

重要:調査には、他のクラスと多くの関係があります。サブクラス化することにした場合。それらすべてをサブクラス化する必要がありますか(各オブジェクトのマスターからデータをコピーするため)?

4

1 に答える 1

4

したがって、基本的に、すべて同じ構造 (コレクション、プロパティなど) を共有する調査がありますが、データは異なる可能性があります..私の考えは、すべてを 1 つのテーブルに格納し、テンプレートと実施されたものを分離する列を作成することです。

さて、あなたが話しているのはプロトタイプです。「テンプレート」調査はプロトタイプです。明らかに、プロトタイプがプロトタイプに基づくインスタンスとまったく同じ構造を持っている場合、同じ構造に対してまったく異なるテーブルを作成するのは愚かで無駄です.両方のセットでミラーリングする必要があります。

プロトタイプ/テンプレートと実施された調査を区別するために列を追加しますか? いいえ、おそらくそうではありません。代わりに、ルート調査テーブルと 1 対 1 の関係を持つ別のテーブルを追加します。この表では、プロトタイプと非プロトタイプを区別するメタデータを少し追加します。

3 つの理由から: 1) 合理的なシステムでは、プロトタイプは調査全体のごく一部になります。2) すべてのプロトタイプを一覧表示したい場合がよくあります。たとえば、新しい調査のベースとなるプロトタイプの選択肢を一覧表示する「新しい調査ウィザードの作成」などです。そして 3) 少し余分なデータを保持するには:

create table survey_prototype (
    id int not null primary key,
    survey_id references survey(id) -- the regular survey table
    wizard_description varchar(80)
    . . . .
);

ここで、調査にも説明があると思いますが、プロトタイプの場合、その説明は「ユーザーが表示する説明を置き換えてください」のようなものですが、wizard_description は「プロトタイプの政治投票」のようなものです。

ここで、プロトタイプ/テンプレートのルックアップでは実施された調査を返す可能性がないため (調査プロトタイプに参加する実施された調査がないため)、getMaster は次のようになります (概念的には、おそらく ORM を使用します)。

ConductedSurvey : Survey {
  //gets the master according to the name
  GetMaster() { "select * from survey_prototype join survey..."
}

重要: Survey には、他のクラスとの多くの関係があります。サブクラス化することにした場合。それらすべてをサブクラス化する必要がありますか (オブジェクトごとにマスターからデータをコピーするため)。

その通りです。ORM から取得したプロトタイプについては、プロトタイプを上書きするのではなく、ディープ コピーして新しい調査を保存する必要があります。とにかくディープ コピーを実行する必要があるため、ディープ コピーでは、プロトタイプが使用する基本クラスをごまかす代わりに、サブクラスのコピーを作成できます。

もちろん、階層の各レベルでその決定を行う必要があります。ディープ コピー変換の各変換ポリシーを 1 つのクラスにカプセル化するとよいでしょう。ビジター パターンはvisit、タイプの (基本) クラスごとに 1 つのオーバーロードされた関数を持っているため、これを行います: so (少なくとも) visitSurvey, visitQuestion, visitAnswer.

ツリー (調査に根ざし、子の質問と孫の回答、つまり複合パターン) を扱うことになるため、コピー/トランスフォーマーでビジター パターンを使用することをお勧めします。あなたのクラスは比較的安定しているので、訪問者はうまく機能します。また、変換の種類ごとに 1 つずつ、複数の異なる具体的なビジターを持つことができます (また、調査を表示またはスコアリングするときは、そのためのビジターも作成できます。ビジターパターンを設定すると無料になります)。

データベースでサブクラス化を処理するには、一般的な nhibernate パターンのいずれかを使用できます。そうすれば、アクセスして変換すると、nhibernate によって自動的にデータベースに保存できる、プロトタイプではない新しい調査ツリーが作成されます。

要約すると、survey_prototype テーブル、プロトタイプを取得します。survey_prototype でルートを要求すると、nhibernate はツリー全体を取得し、コピーされたルートを返すディープ コピー トランスフォーマーを使用してそのツリーにアクセスし、ユーザーに書き込みを許可し、ルートをコピーし、nhibernate にツリーのすべてのノードを再帰的に保存させます。ユーザーがプロトタイプ以外のアンケートを表示する必要がある場合は、nhibernate を使用してアンケートからルートをプルし、display ビジターを使用して表示します。

于 2009-05-04T08:45:27.110 に答える