web-dev-qa-db-ja.com

エンティティVSドメインモデルVSビューモデル

このトピックには、同様の質問が何百もあります。しかし、私はまだ混乱しており、専門家にこれについて助言してもらいたいです。

ASP.NET MVC 4およびEF5を使用してアプリケーションを開発しており、DBファーストアプローチです。

クラスライブラリであり、その中で定義されたすべてのエンティティを保持する別のプロジェクトにデータレイヤーがあります。そして、すべてのリポジトリとドメインモデルで定義されたビジネスレイヤー(使用する正しい用語です)。そして、プレゼンテーション層が来ます。

現在、ビューモデルを定義していません。ビューモデルとしてBLの同じドメインモデルを使用しています。このアプローチでは、1つのマッピングで十分です。

エンティティ<=>ドメインモデル

しかし、私にとっては良いデザインのようには見えません。プレゼンテーション層でビューモデルを定義し、ドメインモデルを使用してプレゼンテーション層とビジネス層の間で通信することを好みます。 BLでは、ドメインオブジェクトをデータエンティティに変換し、DALと通信します。このアプローチを使用して、マッピングを2回使用する必要があります。

モデル<=>ドメインモデル<=>エンティティを表示

ドメインモデルは本当に必要ですか?エンティティを使用してプレゼンテーション層と通信することはできません。プレゼンテーションレイヤーでエンティティを参照している場合、影響はありますか?どんな影響がありますか?

43
Naresh

各レイヤーが何であり、ソリューションでどのような役割を果たしているのかを定義するのに問題があると思います。


データ層

データ層は、データベース/ SharePointリスト/ .csvファイル/ Excelシートにすぎません。データが保存される場所であり、どのような形式でも構いません。したがって、データ層は単なるデータに過ぎないことを忘れないでください。

// ----------------------------
//    Data tier
//        - MySQL
//        - MS SQL
//        - SharePoint list
//        - Excel
//        - CSV
//        - NoSQL
// ----------------------------

データアクセス層

このレイヤーはデータソースを抽象化し、アプリケーションの他の部分がデータソースとやり取りできるAPIを提供します。

データソースがMS SQLデータベースであり、Entity Frameworkを使用してデータにアクセスしていることを考慮してください。抽象化しようとしているのは、データベースとEntity Frameworkであり、EntityごとにData Repositoryがあります。

例...

MS SQLデータベースにCustomersテーブルがあります。 customers表の各顧客はEntityであり、C#コードでそのように表されます。

リポジトリパターンを使用すると、データアクセスコードの実装を抽象化できるため、将来、データソースが変更されても、アプリケーションの残りの部分は影響を受けません。次に、Data Access LayerCustomersRepositoryが必要です。これには、AddRemoveFindByIdなどのメソッドが含まれます。データアクセスコードを抽象化する。以下の例は、これを実現する方法です。

public interface IEntity
{
    int Id { get; set; }
}

public class Customer : IEntity
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime RegistrationDate { get; set; }
}

public interface IRepository<TEntity> where TEntity : class, IEntity
{
    TEntity FindById(int id);

    void Add(TEntity entity);

    void Remove(TEntity entity);
}

public class CustomerRepository : IRepository<Customer>
{
    public Customer FindById(int id)
    {
        // find the customer using their id
        return null;
    }

    public void Add(Customer customer)
    {
        // add the specified customer to the db
    }

    public void Remove(Customer customer)
    {
        // remove the specified customer from the db
    }
}

データアクセス層は、データ層とビジネスロジックの間に属します。

// ----------------------------
//    Business logic
// ----------------------------

// ----------------------------
//    Data access layer
//        - Repository 
//        - Domain models / Business models / Entities
// ----------------------------

// ----------------------------
//    Data tier
//        - MySQL
//        - MS SQL
//        - SharePoint list
//        - Excel
//        - CSV
//        - NoSQL
// ----------------------------

ビジネス層

ビジネスレイヤーはデータアクセスレイヤーの上に構築され、データアクセスの問題を処理するのではなく、厳密にビジネスロジックを処理します。ビジネス要件の1つが英国以外からの注文を防ぐことである場合、ビジネスロジックレイヤーがこれを処理します。


プレゼンテーション層

プレゼンテーション層は単にデータを提示しますが、提示するデータや投稿するデータに注意を払わない場合、あなたは自分自身を設定することになります。ビューモデルはプレゼンテーション層の関心事であるため、ビューモデルを使用することが重要です。プレゼンテーション層はドメインモデルについて何も知る必要はなく、ビューモデルについてのみ知る必要があります。

ビューモデルとは...ビューごとに調整された単なるデータモデルです。たとえば、登録フォームにRegistrationViewModelが含まれ、これらの典型的なプロパティが公開されます。

public class RegistrationViewModel
{
    public string Email { get; set; }
    public string Password { get; set; }
    public string ConfirmPassword { get; set; }
}

プレゼンテーション層は入力検証も処理するため、たとえば、入力されたメールアドレスが正しい形式であるか、入力されたパスワードがプレゼンテーション層の問題であり、ビジネス上の問題ではなく、Data Annotationsを使用して処理できるかどうかを検証します。

public class RegistrationViewModel
{
    [Required]
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Compare("ConfirmPassword")
    public string Password { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public string ConfirmPassword { get; set; }
}

ビューモデルを使用することが重要な理由は、ビジネスモデルはビジネスレイヤーに属し、プライベートのままにする必要があるデータが含まれているためです。たとえば、JSON応答でドメインモデルを公開する場合、ユーザーがデータ全体を公開し、公開するものとそうでないものを選択するのではなく、その名前をアドレスに公開しますが、動作しているようです。


domain modelsentity modelsには違いがあることもここで指摘する必要があります。すでに詳細な答えがあります こちら


横断的関心事

私はこれを簡潔にします:

  • 例外管理
  • ビューモデルのドメインモデルへのマッピング。
93
Aydin

私は専門家ではありませんが、このトピックに関する50セントを共有します。

モデルの表示

ビューモデルを無視することに対する懸念を共有したいと思います。

ビューモデルを使用すると、次のことができます。

  1. ドメインモデルから必要なデータのみを選択する
  2. プレゼンテーションに適切な方法で必要なデータをフォーマットします(たとえば、価格の小数(100.00)を文字列(100.00ユーロ)にフォーマットします)
  3. ビューモデルでDataAnnotationを使用できます。

それで、私はそれを悪いデザインと考えますが、他の人は異なる意見を持っているかもしれません。

ビジネスレイヤーはビューモデルについて何も知らないため、コントローラーにマップする必要があります。

エンティティとドメインモデル

ORMまたはNoRMで永続化できるドメインモデルとしてPOCOを使用して、簡単に始めます。世界で開発されたソフトウェアのほとんどは、システムに大きな損害を与えることはなく、シンプルでもあります。

将来、何らかの理由でWebサービスの使用を開始する場合、リモート呼び出しでのDTO(データ転送オブジェクト)の使用を検討する必要があるかもしれません。そこにある場合、できることは、ドメインモデルを目的のDTOにマッピングする別のレイヤーを持つことです。このレイヤーは、リモートコール(Webサービス)でのみ使用され、プレゼンテーションのビューモデルを保持します。

7
Bruno Costa

追加のクラスを導入する主な利点は、関心の分離です。

  • プレゼンテーション層:これを達成するための前処理および後処理を含む、情報とデータ入力を表示します。フォーマット。
  • ドメイン/ビジネス/アプリケーションロジック:ここで実際の作業は完了です
  • 永続層:データの保存と取得

これは、ViewModelとDomainエンティティの2つのモデルクラスのみで実現できます。永続化されたエンティティに類似した個別のモデルクラスを使用してドメインロジックをモデリングする代わりに、ドメインエンティティを使用するサービスクラスに実装します。ドメインエンティティには、独自のプロパティを処理するロジックが最大である必要があります(たとえば、2つのプロパティの結合値を有効な状態に保つ)。複数のドメインエンティティがユースケースの影響を受ける場合、サービスクラスでこのユースケースをモデル化します。エンティティ間の関係をエンティティクラスに直接管理するロジックを配置すると、コードはすぐに維持できなくなります(私を信頼して、試してみました)。

永続性のあるエンティティをViewModelとして使用することはお勧めしません。これは、表示に関する懸念事項(例:[DisplayName])永続性の懸念(例:[ForeignKey])。

1