[解決済み】サービスは常にDTOを返すべきですか、それともドメインモデルも返すことができますか?
質問
大規模なアプリケーションを設計しているのですが、DDDに基づく多層アーキテクチャを使用しています。
私たちは、データ層(リポジトリの実装)、ドメイン層(ドメインモデルとインターフェイスの定義 - リポジトリ、サービス、作業単位)、サービス層(サービスの実装)でMVCを構成しています。これまでのところ、すべての層でドメインモデル(主にエンティティ)を使用し、DTOはビューモデルとしてのみ使用しています(コントローラで、サービスがドメインモデルを返し、コントローラがビューモデルを作成し、ビューに渡されます)。
DTOの使用、不使用、マッピング、パスについて数え切れないほどの記事を読みました。明確な答えがないことは理解していますが、サービスからコントローラーにドメインモデルを返してもいいのか悪いのかよくわかりません。もしドメインモデルを返したとしても、コントローラは常にビュー専用のビューモデルを作成するため、ビューに渡されることはありません - この場合、合法的に見えます。一方、ドメインモデルがビジネスレイヤー(サービスレイヤー)から離れると、違和感があります。サービスによっては、ドメインで定義されていないデータオブジェクトを返す必要があり、その場合、マッピングされていない新しいオブジェクトをドメインに追加するか、POCOオブジェクトを作成しなければなりません(あるサービスはドメインモデルを返し、あるサービスは事実上DTOを返すので、これは醜いことです)。
ビューモデルを厳密に使用する場合、コントローラまでドメインモデルを返しても良いのか、それともサービス層との通信には常にDTOを使用すべきなのか、ということです。もしそうなら、サービスが必要とするものに基づいてドメインモデルを調整してもいいのでしょうか?(DTOにこだわるのであれば、サービス層で定義すべきなのでしょうか?(DTOを使うべきことが明らかな場合(例:サービスが多くのビジネスロジックを実行し、新しいオブジェクトを作成する場合)と、ドメインモデルだけを使うべきことが明らかな場合(例:メンバーシップサービスが貧弱なユーザーを返す場合、ドメインモデルと同じDTOを作成してもあまり意味がないようです)があります - 私は一貫性と優れた実践を好みます。
記事 ドメイン vs DTO vs ViewModel - どのように、いつ使うのか? (そして他の記事も)私の問題と非常によく似ていますが、この質問(複数可)には答えていません。記事 EFでリポジトリパターンのDTOを実装すべき? も似たようなものですが、DDDは扱ってないです。
一方、良いデザインパターンとプラクティスは、アプリケーション全体の設計に役立ち、関心事の分離に役立つので、特定のパターンを使うことは、少なくとも現時点では必要ではありませんが、使いたいと思っています。
どのように解決するの?
<ブロッククオートドメインモデルがビジネス層(サービス層)から離れると違和感がある
内臓を引っ張り出しているような気分になりますよね?Martin Fowlerによれば、サービスレイヤーはアプリケーションの境界を定義し、ドメインをカプセル化する。言い換えれば、ドメインを保護するのです。
<ブロッククオートドメインで定義されていないデータオブジェクトをサービスが返す必要がある場合がある
このデータオブジェクトの例を教えてください。
DTOに厳密にこだわるのであれば、サービス層で定義すべきでしょうか?
はい、レスポンスはサービスレイヤーの一部だからです。もしそれが他のどこかで定義されているなら、サービス層はその他のどこかを参照する必要があり、ラザニアに新しい層が追加されることになります。
<ブロッククオートそれとも、サービス層との通信には常にDTOを使用すべきでしょうか?
DTOはレスポンス/リクエストオブジェクトなので、通信に使うなら理にかなっています。もし、プレゼンテーション層(MVC-Controllers/View, WebForms, ConsoleApp)でドメインモデルを使用している場合、プレゼンテーション層はドメインと密接に結合しており、ドメインを変更するとコントローラを変更する必要があります。
<ブロッククオートドメインモデルと同じDTOを作ってもあまり意味がないような気がするのですが......。)
これは、新しい目から見たDTOのデメリットの一つです。今、あなたはこう思っています。 コードの重複 しかし、プロジェクトが拡大するにつれ、特に異なるチームが異なるレイヤーに割り当てられるチーム環境では、より理にかなったものになるでしょう。
DTOはアプリケーションにさらなる複雑さを加えるかもしれませんが、レイヤーも同様です。DTOはシステムの高価な機能であり、無料で手に入るものではありません。
DTOを使用する理由
この記事では、DTOを使用するメリットとデメリットの両方を紹介します。 http://guntherpopp.blogspot.com/2010/09/to-dto-or-not-to-dto.html
概要は以下の通りです。
使用する場合
- 大規模なプロジェクトの場合。
- プロジェクトのライフタイムが10年以上である。
- 戦略的、ミッションクリティカルなアプリケーションである。
- 大規模チーム(5名以上)
- 開発者が地理的に分散している
- ドメインとプレゼンテーションが異なる。
- オーバーヘッドのデータ交換を減らす(DTOの本来の目的)。
使用しない場合
- 小中規模プロジェクト(最大5名)
- プロジェクト寿命は2年程度
- GUI、バックエンドなどの別チームはありません。
DTOに対する反論
- コードが重複する。
- 開発時間、デバッグのコスト。(DTO生成ツール使用 http://entitiestodtos.codeplex.com/ )
- 両方のモデルを常に同期させる必要があります。(個人的には、変更の波及効果を知るのに役立つので、これが好きです)
- 開発コスト。追加マッピングが必要。(自動マッピングを使用する。 https://github.com/AutoMapper/AutoMapper )
- なぜデータ転送オブジェクト(DTO)はアンチパターンなのですか?
DTOを使った引数
- DTOがない場合、プレゼンテーションとドメインは緊密に結合されています。(小規模なプロジェクトではこれでOK)
- インターフェース/APIの安定性
- 絶対に必要な属性のみを含むDTOを返すことにより、プレゼンテーション層の最適化を提供することができる。使用方法 linq-projection を使えば、エンティティを丸ごと引っ張る必要はない。
- 開発コストを削減するために、コード生成ツールを利用する
関連
-
[解決済み】同じキーのアイテムがすでに追加されています。
-
[解決済み] プロジェクトのデフォルトのXMLネームスペースはMSBuild XMLネームスペースである必要があります。
-
[解決済み] ファイルまたはアセンブリ 'System.Web.Mvc' を読み込めませんでした。
-
[解決済み] Automapper のタイプマップ構成がない、またはサポートされていないマッピング - エラー
-
[解決済み] ルート値を含むURL.Action()
-
[解決済み] ASP.Net MVCのmodelStateからすべてのエラーを取得する方法は?
-
[解決済み】ASP.NET MVC 3 RazorでAjax.BeginFormを使用する。
-
[解決済み】AutoMapper.CreateMapsをどこに配置するか?
-
[解決済み] 型名または名前空間名 'DbContext' が見つかりませんでした [閉鎖]。
-
[解決済み] Visual Studio 2012 または Visual Studio 2013 で古い MVC プロジェクトを開くにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 既存のデータベースの選択されたテーブルからDbContextをScaffoldすることができますか[重複]。
-
[解決済み] MVCで、文字列の結果を返すにはどうしたらいいですか?
-
[解決済み] MVCにおけるViewModelとは?
-
[解決済み】認証や認可に失敗した場合、AuthorizeAttributeがログインページにリダイレクトされるのはなぜですか?
-
[解決済み] [Solved] ASP.NET MVCでアクションの絶対URLを見つけるにはどうすればよいですか?
-
[解決済み】MVC4 DataType.Date EditorForがChromeで日付の値を表示しない、Internet Explorerでは問題なし。
-
[解決済み】HTTPエラー500.19とエラーコード: 0x80070021
-
[解決済み] asp.net mvc: なぜ Html.CheckBox は追加の隠された入力を生成するのですか?
-
[解決済み] HTMLヘルパーでURLを生成する
-
[解決済み] なぜデータ転送オブジェクト(DTO)はアンチパターンなのか?