web-dev-qa-db-ja.com

なぜ2つのクラス、ビューモデルとドメインモデルなのか?

ドメインモデルをビューモデルとして使用するのは悪いことかもしれません。ドメインモデルにIsAdminという名前のプロパティがあり、ユーザーを作成するためのコントローラーの作成アクションがある場合、誰かが私のフォームを変更して、それをPOST IsAdmin = trueフォーム値にしたとしてもビューでそのようなテキストフィールドを公開しないでください。モデルバインディングを使用している場合、ドメインモデルをコミットすると、そのユーザーが管理者になります。したがって、ソリューションは、ビューモデルで必要なプロパティのみを公開し、 AutoMapperのようなツールを使用して、返されるビューモデルオブジェクトのプロパティ値をドメインモデルオブジェクトのプロパティ値にマップします。ただし、クラスのバインド属性を使用して、バインドする必要があるプロパティとバインドしないプロパティをモデルバインダーに指示できることを読みました。では、本質的に同じものを表す2つの別々のクラス(ドメインモデルとビューモデル)を作成し、それらをマッピングする際にオーバーヘッドが発生する理由は本当に何ですか?それはコード編成の問題ですか?もしそうなら、私はどのように利益を得ますか?

[〜#〜]編集[〜#〜]

ドメインモデルとは別のビューモデルで私が遭遇した最も重要な理由の1つは、複雑なUIを管理するために(MartinFowlerのPMパターンに基づく)MVVMパターンを実装する必要があることです。 。

26
enamrik

私のドメインモデルでは、必要なフィールドを取得する方法の85%が得られますが、ビューで必要な値の100%をカバーしたことは一度もないことがわかりました。特に、アクセス許可と、ユーザーがビューの特定の部分にアクセスできるかどうかについてはそうです。

私が従おうとしている設計コンセプトは、私の見解にできるだけロジックを持たないことです。これは、ビューモデルに「CanViewThisField」や「CanEditThisField」などのフィールドがあることを意味します。私が最初にMVCを始めたとき、ドメインモデルをビューモデルにしていて、ビューをすっきりさせるために1つまたは2つのフィールドが必要なシナリオに常に遭遇していました。それ以来、 View Model/Model Builder ルートを使用しましたが、それは私にとって素晴らしい働きをしました。私はもうコードと戦うことはありませんが、ドメインモデルに影響を与えることなく、必要に応じてビューモデルを拡張することができます。

19
Nick DeVore

ViewModelを使用するもう1つの理由は、大量のデータセットをページングすることです。ビューにPersonの配列を渡すことができます(Person[])ただし、ページ数、現在のページ数、ページのサイズなどのメタデータは、Personクラスに属しません。

したがって、PersonListViewModelはこの問題を解決します。

16
Andrei Rînea

ViewModelは、ビューに必要なメンバーのみを保持します。これらは通常、基礎となるドメインモデルの単純化または「フラット化」と考えることができます。

次のように考えてください。

  • ViewModel:これはこのビューでレンダリングするのに適切なデータです
  • ドメインモデル:これは、アプリケーションがすべての機能を実行するためにこのエンティティについて必要とするすべての情報です

たとえば、私のOrderクラスには、 composition アソシエーションであるCustomerというメンバーがあります。つまり、私のOrderにはaCustomerがあります。 。このCustomerオブジェクトには、Firstname、Lastnameなどのメンバーがあります...しかし、これを注文の「詳細」ビューまたは注文と注文した顧客のリストに表示するにはどうすればよいですか?

そうですね、ViewModelを使用すると、CustomerNameメンバーを持つOrderListItemViewModelを作成でき、FirstnameとLastnameの組み合わせをCustomerオブジェクトからこれにマップできます。これは手動で行うことも、 Automapper などを使用して行うこともできます。

このアプローチを使用すると、さまざまなビューに固有の複数のOrderViewModelを作成できます。注文リストビューは、注文詳細ビューとは異なる方法で顧客名を表示する場合があります。

ViewModelsのもう1つの利点は、ビューの基になるドメインオブジェクトに必要のない無関係なデータを削減できることです。注文のリストを表示している場合、本当にすべての顧客の連絡先情報、請求の詳細などを表示したいですか?それはリストの目的にもよると思いますが、おそらくそうではありません。

3
A. Murray

あなたはあなたのdomain model classesのみ使用されますinternally;つまり、クライアントに送信されることはありません。これが、サービスモデルタイプ(ビューモデルタイプ)の使用目的です。これらは、クライアントとサービスの間を行き来するデータを表します。

2

特定の方法でデータを表示する必要がある場合(つまり、日付をmm/dd/yyyyとyyyy/mm/ddの形式で表示する)、ドメインではなくビューでこのプロパティを作成する方が簡単な場合があります。モデル。データベース内の列へのマッピングが必要です(または必要です)。

2
khr055