1

いくつかの特徴を持つクライアント/サーバー ソリューションのアーキテクチャに関するアドバイスを探しています。

クライアントはかなり厚いものであり、サーバーは主に永続性、同時実行性、およびインフラストラクチャの問題に任せられています。サーバーには、機密情報と公開情報の両方を含む多数のエンティティが含まれています。たとえば、エンティティが人であり、社会保障番号と名前が機密情報であり、年齢が一般に公開されているとします。

クライアントを起動すると、機密情報を開示することなく、多数のエンティティがユーザーに表示されます。ユーザーはいつでもログインしてサーバーに対して認証することを選択できます。認証が成功すると、機密情報へのアクセスがユーザーに許可されます。

クライアントはドメイン モデルをホストしており、これをある種の「遅延読み込み」として実装し、最初のリクエストでエンティティをインスタンス化し、後で機密データで更新することを考えていました。機密情報が開示されていない場合、エンティティ ゲッターは機密情報に対して例外をスローします。fe:

class PersonImpl : PersonEntity
{
    private bool undisclosed;

    public override string SocialSecurityNumber {
        get {
            if (undisclosed)
                throw new UndisclosedDataException();

            return base.SocialSecurityNumber;
        }
    }
}

別のより友好的なアプローチは、値が非公開であることを示す値オブジェクトを持つことです。

get {
    if (undisclosed)
        return undisclosedValue;

    return base.SocialSecurityNumber;
}

いくつかの懸念:

  • ユーザーがログインしてからログアウトすると、機密データは読み込まれますが、もう一度開示する必要があります。
  • このタイプの機能はドメイン内に属し、一部のインフラストラクチャの実装 (つまり、リポジトリの実装) ではないと主張することができます。
  • いつものように、より多くのプロパティを扱う場合、このタイプの機能がコードを乱雑にするリスクがあります。

洞察や議論は大歓迎です!

4

2 に答える 2

2

これは実際にビュー モデルを使用した優れた例だと思います。あなたの懸念は、エンティティに含まれるデータのため、エンティティの消費に直接関係しているようです。エンティティを UI まで渡す代わりに、ドメイン内のみに存在するように制限することができます。つまり、エンティティはドメインに出入りせず、ほとんど/すべてのアクティビティはコマンド/クエリ アプローチで行われます。リポジトリで。リポジトリは、エンティティの代わりにビュー モデルを返します。

では、これはどのように/なぜ適用されるのでしょうか? 実際には、2 つの異なるビュー モデルを持つことができます。1 つは認証済みユーザー用、もう 1 つは非認証ユーザー用です。認証されていないモデルではなく、認証されたビュー モデルの機密データの実際の値を公開します。それらを共通のインターフェイスから派生させ、オブジェクトの種類ではなくインターフェイスに対してコーディングすることができます。認証されていないユーザーの具体的な実装については、非機密データを入力するだけで、機密ゲッターに必要なことを任せることができます。

いくつかの点に関する私の意見

  • 私はエンティティの遅延読み込みが好きではありません。遅延読み込みはデータ アクセスの責任であり、実際にはモデルの一部ではありません。私にとって、これは、ページングやソートと同様に、自分のドメインで激しく避けているものの最上級のメンバーです。これらのアイテムを関連付ける方法については、ID ポインターを介してオブジェクトを他のエンティティに疎結合することをお勧めします。これらのエンティティのいずれかに含まれるデータが必要な場合は、それをロードできます。ある意味では遅延読み込みのようなものですが、これを行うことで、ドメイン モデル自体では決して起こらないようにしています。
  • 私は getter で例外をスローするのが好きではありません。一方、セッターは問題ありません。このように見ています。エンティティは常に有効な状態である必要があります。ゲッターはエンティティの状態に影響を与えませんが、セッターはそうします。セッターをスローすると、モデルの整合性が強化されます。2 ビュー モデル アプローチを使用すると、ロジックをプレゼンターに移すことができます。したがって、基本的には、「ユーザーが許可されていないタイプの場合はこれを実行し、そうでない場合は別のことを実行します」のようなことを行うことができます。あなたが言及しているのは、最終的にはデータがユーザーにどのように提示されるかというケースであり、モデルにとっては重要ではないため、うまく適合すると思います. 一般に、null にすることができるプロパティには null 許容型を使用し、ゲッターには何も強制しません。通常、それはその責任の一部ではないためです。その代わり、

明らかな欠点は、ビュー モデルを使用するために必要なコーディングが増えることですが、ドメインからプレゼンテーションとビューを切り離すという明らかな利点があります。また、特定のビュー モデルが特定のタイプのデータを返せないことを確認できるユニット/統合テストにも役立ちます。

ただし、AutoMapperに似たものを使用して(プラットフォームが何であるかによって異なります)、エンティティからビュー モデルを作成するのに役立ちます。

于 2010-05-19T13:24:38.607 に答える
0

OpenIdを作成せずに質問を投稿するというミスを犯したため、ここにコメントする必要があるようです(?)。

まず第一に、回答に時間を割いていただきありがとうございます。モデルがどのように機能するかよりも、データがどのように表示されるかに関係があることは確かです。ただし、いくつかのことを明確にする必要があると感じています。ドメイン モデル / エンティティが UI から直接参照されることはありません。UI とビジネス モデルを分離するために、DM-V-VM パターンのバリアントを使用しています。一般的に、遅延読み込みとリポジトリの実装については、シリアライゼーション、ダーティ トラッキング、遅延読み込みなどを処理するインフラストラクチャ レイヤーにエンティティを実装しています。

したがって、ドメイン層には次のようなエンティティがあります。

class Entity {
    virtual string SocialSecurityNumber { get; }
}

また、インフラストラクチャ レイヤーは、サーバーからエンティティを更新および復元できるようにするために、いくつかの他の機能を追加します。

class EntityImpl : Entity {
    bool isDirty;
    bool isLoaded;
    // Provide the means to set value on deserialization
    override string SocialSecurityNumber;
}

そのため、遅延読み込みの動作はインフラストラクチャ レイヤーで実装され、ドメイン レイヤーからは見えません。

ゲッターをスローするのは良くないことに同意しますが、匿名ビューモデルがデータを取得する方法に懸念があります。現時点では、エンティティのリストを取得するために、ビューモデルはドメイン リポジトリへの参照を保持します。1 つは認証済みの (したがって開示された) エンティティ用で、もう 1 つは認証されていないユーザー用です。 ?

于 2010-05-20T12:18:31.207 に答える