web-dev-qa-db-ja.com

ビューレイヤーのDTOまたはドメインモデルオブジェクト?

これはおそらく古くからある質問であることは知っていますが、より良い方法は何ですか?アプリケーションのすべてのレイヤーでドメインモデルオブジェクトを使用し、JSPで値を直接それらにバインドします(JSFを使用しています)。または、ドメインモデルオブジェクトをDAOまたはサービスレイヤーのDTOに変換し、軽量のDTOをプレゼンテーションレイヤーに送信します。

データベースを変更するとすべてのDTOが変更されるため、DTOを使用しても意味がないと言われていますが、モデルオブジェクトをどこでも使用すると、影響を受けるモデルオブジェクトを変更するだけで済みます。ただし、DTOの使いやすさと軽量性はそれを上回るようです。

アプリはHibernateモデルオブジェクトを使用し、独自のカスタム作成モデルオブジェクトを使用していることに注意してください(つまり、DBセッションにバインドされておらず、常にデタッチされています)。上記のシナリオのいずれかは、厳密なモデルオブジェクトパターンに対してより有益ですか? Hibernateの使用は、遅延初期化例外などの点で大きなPITAでした。

私は議論を進めるためにこの質問を編集しています(私がこれを正しく行っているかどうかはわかりません):

私がモデルオブジェクトで抱えている問題は、それらがまったく柔軟性がないことです。以下のコメントは、モデルオブジェクトをすべてのレイヤーで使用できるようにアプリケーションを設計する必要があることを示しています。どうして?ユーザーがとんでもない機能を望んでいる場合、私はそれらに「モデルオブジェクトではうまく機能しない」と言うべきですか?

単純明快ですが、モデルオブジェクトが機能しない場合があります。あなたが持っているかもしれません:

public class Teacher {
    List<Student> students;
    [tons of other Teacher-related fields]
}
public class Student {
    double gpa;
   [tons of other Student-related fields]
}

しかし、おそらくそのすべての情報は必要ありません。必要なのは、先生の姓、彼らが今年教える生徒の数、およびすべての生徒を合わせた平均GPAだけです。その場合はどうしますか?完全な教師情報と生徒の関係を取得し、コードで生徒のリストの数を取得し、内部のすべてのgpaの合計平均を計算しますか?これは、「String lastName」、「int numStudents」、および「double CombinedGpa」を使用して単純にDTOを作成するよりも、もっと努力のようです。

私の考えはこれらで構成されているように聞こえるかもしれませんが、モデルオブジェクトをすべてのインスタンスで完全にクリーンに使用できるアプリケーションではまだ作業していません。通常とは異なるユーザーの要求を伴う通常の実際のアプリケーションは、そのようには機能しません。

49
sma

それは実際にはアプリケーションの複雑さに依存します。ドメインオブジェクトをビューレイヤーに混在させることには、2つの影響があります。

  1. ビューレイヤーで必要なものに対応するようにドメインオブジェクトを変更したくなるでしょう
  2. ビューレイヤーには、ドメインオブジェクトが提供するものとビューが実際に必要とするものとの不一致によって引き起こされる余分な複雑さが含まれます。この複雑さを回避することはできないかもしれませんが、おそらくビューレイヤーに属していません。

ドメインオブジェクトが単純でビューが少ない場合は、DTOをスキップするのが最も簡単です。

一方、ドメインモデルが進化して複雑になる可能性が高く、ビューが多数で変化する可能性がある場合は、ビュー固有のオブジェクトを用意することをお勧めします。 MVCの世界では、ViewModelを使用するのが一般的であり、私には非常に理にかなっています。

33
srmark

ドメインオブジェクトに対する別の投票。ドメイン駆動設計に関する限り、ドメインモデルは王様であり、可能な限り使用する必要があります。アプリケーションは、ほとんどのレイヤー(インフラストラクチャレイヤー)がドメインオブジェクトを使用できるように設計する必要があります。

DTOは、オブジェクトをシリアル化する必要がある場合にのみ役立つと思います。ネットワーク経由または互換性のないアーキテクチャへの転送がない場合、それらは使用しません。 DTOパターンは、シリアル化をドメインオブジェクトから除外するのに役立ちます。 UI /ドメインの相互作用にはシリアル化が必要ないことを考慮して、単純化し、実際のオブジェクトを使用してください。

8
Igor Zevaka

DTOを持つことは、一般的に反パターンではないと思います。それらを使用する人やシステムはたくさんあり、ドメインモデルから独立して設計およびモジュール化できる分離ビューレイヤーが得られます。可能な限りドメインオブジェクトを使用する必要があることに同意しますが、ビューレイヤーをドメインモデルに直接結び付けるときに問題が発生する可能性があるシナリオがあります。

私は、ドメインオブジェクトをラップし、ほとんどの操作をそれらに委任するビューモデルで良い経験をしました。これにより、ビューとドメインレイヤーが分離され、ドメインオブジェクトの柔軟な構成が可能になりますが、IDEがサポートしているため、実装する作業はそれほど多くありません委任パターン。

7
bennidi

私の意見では、すべてのレイヤーでドメインモデルオブジェクトを使用してもまったく問題はありません。あなたはすべての情報が必要ではないと言った。 JSPを使用しているときは、必要なデータのみを使用してください。誰もがすべてのプロパティをフェッチすることを強制していません。また、GPA、学生数などを取得するには、オブジェクトのプロパティに関連する計算を行う必要があると述べました。3つのオプションがあります。適切なデータを返すドメインモデルオブジェクトに合成プロパティを作成し、ニースをまとめますそしてきちんとした;コントローラー層またはサービス層のいずれかで計算を行い、適切なゲッターを通じてそれらを公開します。または、JSP内ですべて処理します。とにかくデータを取得/コンパイル/複雑化する必要があるので、DTOを使用してさらに複雑にする必要があります。

さらに、各DTOを使用して、a。)維持する必要のある追加のクラスを作成します。b。)DTOを構築および移植するクラスのどこかに少なくとも1つの追加のメソッド(DAO、ファクトリーメソッドなど)を作成します。 。メンテナンスの増加= 6か月後の不幸な開発者。

したがって、DTOに対する私の議論があります。私はそれらを使用していますが、速度やメモリの使用量を最適化する必要がある場合や、完全なドメインモデルオブジェクトをハイドレートするコストが高すぎる場合など、特定のシナリオでのみ使用します。 Webサービスは、DTOの使用を好む好例です。

2
Aquarelle

ドメインオブジェクトの送信に問題があるシナリオ:

  1. 集約された情報またはUIレイヤーに送信された他のタイプの「計算フィールド」(例:Flex/GWT)が必要で、ドメインオブジェクトを台無しにしたくない場合
  2. 循環オブジェクトグラフをシリアル化する必要がある場合があります(この例では、StudentにListリレーションがあった場合)、一部のプロトコルには問題があります
  3. フレームワークシリアライザーを処理する場合のHibernate LazyInitializationException(FlexのblazeDS/GWTシリアライザー)

それらの状況における明確な答えかどうかはわかりません

2
Al1998

クラスの動作、またはその内部メソッドは、その動作に関係のないレイヤーに公開されるべきではありません。動作ではなくデータを転送します。ドメイン内のドメインオブジェクトを使用します。 Webは制御されたドメインではなく、UI開発者はドメインの動作に注意する必要はありません。データだけに注意してください。

ドメインはカプセル化され、ドメインの状態に関係のない誰かによる変更から保護される必要があります。

漏出行動は最良の習慣ではありません。

小規模なプロジェクトの場合は、正しい原則で構築します。そうすることで、私たちは常に、自分が何をするのか、どのように行うのかを常に心に留めています。

0
Ilan Y