4

memberユーザーがまたはになることができるシステムの場合、adminその役割を持つユーザーはmember、定期的なサブスクリプションで料金を支払うか、無料のアクセス権を付与される必要があります。

私の現在のアプローチ:

  • ユーザーにはuserデータベーステーブルがあります。
  • subscriptionテーブルには、ユーザーがサブスクリプションを持っている場合のレコードが含まれます。
  • subscription_event表には、各請求または失敗した支払いが記録されます。これを照会して、最後のイベントが実際に支払いに成功したかどうかを確認できます。

しかし、ユーザーに「無料」アクセスが許可されているかどうかをどのように記録すればよいでしょうか。

  • complimentary_subscription外部キーとしてユーザーIDを持つ別のテーブルがありますか?
  • それらの特別な「サブスクリプション」をsubscription?に記録します。
  • is_complimentaryまたは、やcomplimentary_expires_date?などの列のユーザー行に別の列を追加します。
  • expiresより一般的な列をユーザー行に追加しますか?
4

2 に答える 2

8

質問レビュー

@leanneが言ったように、あなたはSubscriptionその専門分野が、たとえば、MonthlySubscriptionComplimentarySubscriptionこの答えの名前を付けるために)であるモデルを作成しています。

サブスクリプションが期限切れになる可能性があることを知っています:

  • の場合、MonthlySubscriptionこれはユーザーが今月のサブスクリプションを支払わなかった場合に発生します
  • の場合ComplimentarySubscription、有効期限はユーザーに割り当てられたときに割り当てられます

ご覧のとおり、ExpirationDateはすべての重要な属性ですSubscriptionが、保存方法はそれぞれ異なります。前者の場合は最後のイベントに基づいて計算する必要がありますが、後者の場合は直接取得できます。

データベースでの継承の処理

したがって、このサンプルモデルをデータベーススキーマにマップするには、 MartinFowlerの『 Patterns of Enterprise Application Architecture 』の本で説明されているクラステーブル継承パターンを使用できます。その意図は次のとおりです。

「クラスごとに1つのテーブルを持つクラスの継承階層を表します」。

基本的に、クラス間で共通の属性を共有するテーブルがあり、各クラスに固有の属性を別々のテーブルに格納します。

これを念頭に置いて、提案したオプションを確認しましょう。

  • complimentary_subscription外部キーとしてユーザーIDを持つ別のテーブルがありますか?

特定の詳細を格納するための個別のテーブルComplimentarySubscriptionがあることは良いことのように聞こえますが、これをテーブルに関連付けないと、aと。のsubscription両方を持つユーザーになってしまう可能性があります。その外部キーは、ユーザーがサブスクリプションを持っているかどうかを示すテーブルを指している必要があります(ユーザーごとに最大1つのサブスクリプションを適用する必要があります)。MonthlySubscriptionComplimentarySubscriptionsubscription

  • それらの特別な「サブスクリプション」をsubscription?に記録します。

はい、ユーザーが毎月または無料でサブスクリプションを持っていることを記録する必要があります。ただし、金額がゼロの特別なサブスクリプションを記録するようなことを考えている場合は、適切なモデルを検索するのではなく、現在の設計に一致するソリューションを探しています(そうでない場合もあります)。

  • is_complimentaryまたは、やcomplimentary_expires_date?などの列のユーザー行に別の列を追加します。

個人的には、これが属していない場所に情報を入れているので、これは好きではありません。それを考慮して、無料サブスクリプションの有効期限をどこに保存しますか(月額サブスクリプションの場合は、有効期限を保存せずに計算していることに注意してください)。そのすべての情報がそれ自身の「家」を求めているようです。また、後で新しいタイプのサブスクリプションを追加する必要がある場合、そのテーブルは乱雑になり始めます。

  • expiresより一般的な列をユーザー行に追加しますか?

これを行う場合、が変更されるたびにデータ同期を処理する必要がありますsubscription_event(月額サブスクリプションの場合)。通常、私はこのデータ重複の状況を回避しようとします。

サンプルソリューション

新しいタイプのサブスクリプションを追加するときに拡張性を優先するために私が行うことは、との間でsubscription共有される詳細を格納するテーブルを用意し、行が関連するサブスクリプションの種類を区別できる列キーを追加することです。MonthlySubscriptonComplimentarySubscriptiontype

subscription次に、親行を参照して、各サブスクリプションタイプに固有の詳細を独自のテーブルに格納します。

Subscriptionデータを取得するには、行の特定のtype列値の正しいタイプのインスタンス化を担当するオブジェクトが必要ですsubscription

type列の値を定義する方法、マッパーオブジェクトを使用してSubscriptionインスタンス化を行う方法などの詳細については、「エンタープライズアプリケーションアーキテクチャのパターン」の本のパターンを参照してください。


2012年1月3日更新:type列を定義および処理するための代替手段

コメントに@enoinocによって投稿された次の質問を明確にするための更新があります。

特に提案された列の場合、これは、支払いなしで期限切れになるまでの月数など、さまざまなタイプのサブスクリプションを説明typeするテーブルを指す外部キーである可能性があります。Plansそれは論理的に聞こえますか?

Plans編集する必要のない静的な情報でない限り、その情報をテーブルに含めてもかまいません。その場合は、ソリューションを過度に一般化して、その知識を対応するSubscriptionサブクラスに入れないでください。

外部キーアプローチについて、私はそのように進むいくつかの欠点を考えることができます:

  • 目標は、テーブルSubscriptionの各行に使用するサブクラスを知ることであることを忘れないでください。Plans取得したのが外部キー値(たとえば整数)だけの場合は、その値を使用するクラスにマップするコードを作成する必要があります。それはあなたのために余分な仕事を意味します:)
  • 不必要な余分な作業を行う必要がある場合は、メンテナンスが面倒になる可能性があります。新しいプランを追加するたびに、マッピングコードに外部キー値をハードコーディングすることを覚えておく必要があります。
  • データベースのエクスポート/インポート操作が不適切な場合、外部キーが変更される可能性があります。その場合、マッピングコードは機能しなくなり、ソフトウェアを再度デプロイする必要があります(または少なくとも変更された部分)。

提案された解決策

私がすることは、テーブルのtype列に入れることです。その列には、特定の行からPlans権利を構築する方法を知っているクラスの名前が保持されます。Subscription

しかし、なぜ各タイプを構築するためのオブジェクトが必要なのSubscriptionですか?各タイプのオブジェクトを構築するためにさまざまなテーブル(subscription_eventおよび)からの情報を使用するため、その動作を分離してカプセル化することは常に良いことです。complimentary_subscription

Plansテーブルがどのように見えるか見てみましょう:

-計画表-

Id | 名前| タイプ| その他の列...

1 | 毎月| MonthlySubscriptionMapper |

2 | 無料| ComplimentarySubscriptionMapper|

それぞれがデータベースから行を取得し、サブクラスの適切なインスタンスを提供するSubscriptionMapperメソッドを定義できます(または例では)。Subscription MapFrom(Row aRow)SubscriptionMonthlySubscriptionComplimentarySubscription

最後に、列で指定されたマッパーのインスタンスを取得するにはtype(厄介なステートメントを使用せずにifcase、列の値からクラス名を取得し、リフレクションを使用して、そのクラスのインスタンスを作成できます。

于 2012-01-01T20:03:00.027 に答える
1

それにもかかわらず、無料のサブスクリプションはサブスクリプションです。その支払額とサブスクリプションの価格はゼロになります。その有効期限は、無料サブスクリプションと通常サブスクリプションの有効期限として設定したものになります。

現在の設定では、これらの要因に基づいて無料のサブスクリプション/ユーザーを正常に照会できない場合にのみ、個別の列またはテーブルが必要になります。

注:ここでは、現在ユーザーをサブスクリプション価格に関連付けていると想定しています。とにかく、サブスクリプションの価格が将来変更された場合や、定期的なユーザーやプロモーションユーザーなどの割引も有効にしたい場合は、そのことを知っておく必要があります。

于 2011-12-31T20:19:21.500 に答える