エンティティからDTOへの使用


15

基本的な階層型Webアプリケーションのフローを考え出そうとしており、競合する情報をオンラインで読んでいます。私が理解しようとしているのは、何らかのマッパーを使用して、DAOからサービスレイヤーへのDTOオブジェクトを引き続き使用する利点があるかどうかです。

私が予見する基本的な流れは次のとおりです。

  1. UIモデル/フォーム->コントローラー
  2. コントローラーはモデルをドメインオブジェクト(エンティティ)に変換します
  3. ドメインオブジェクト->サービスレイヤー
  4. ドメインオブジェクト-> DAO
  5. DAO->ドメインオブジェクト
  6. サービス-> UI
  7. UIはドメインをUIモデルに変換します

DTOに従った場合、DAOはエンティティではなくDTOを返します。(少なくともJavaでは)エンティティがアノテーション付きのPOJOになったため、DTOがわずかに機能しなくなったようです。つまり、メモリフットプリントが非常に小さくなっています。

これは事実ですか、それともDTOを使用してドメインオブジェクトをDAOレイヤー内に完全にカプセル化する必要がありますか?また、この場合、サービスレイヤーはDAOに何を渡しますか?

本当にありがとう!

回答:


20

私によると、たとえばJPAが管理するBeanのような永続的なPOJOを渡すのは良い習慣ではありません。

どうして?

次の3つの主な理由があります。

  1. 遅延コレクションの潜在的な問題。http://java.dzone.com/articles/avoid-lazy-jpa-collections
  2. エンティティには動作が含まれている必要があります(Anemicドメインモデルに反して)予期しない動作をUIに呼び出させたくない場合があります。
  3. 貧弱なドメインモデルの場合、モデルに新しい変更を加えるたびにUIが破損する可能性があるため、モデル構造をUIに公開したくない場合があります。

サービスレイヤーでエンティティを両方向で対応するDTOに変換することを好みます。DAOはまだエンティティを返します(変換を保証するのはその仕事ではありません)。


したがって、これを正しく理解している場合、サービスは基本的にDTOオブジェクトのみを処理し、UIとDAOの両方の仲介者として機能します。また、ポイント3では、DTOを実行可能なUI要素に変換する必要があるため、DTOも更新が必要なため、ドメインの更新によってUIが破損することはありません。
ダルド

1
@dardo UI要素はDTOです。最悪の場合、サーバー側でいくつかのサービスを呼び出す前にDTOに変換する必要があります。DTOは頻繁に変更される可能性は低く、UIのニーズに焦点を合わせたエンティティからの適応のみがあります。また、サービスレイヤーはDTOとエンティティの両方を考慮する必要があります。
Mik378

ああ、理解できなかったしゃっくりがあります。私が働いている貧血領域モデルはかなり一般的であり、サービス層をより薄くするためにパラダイムを少し変えようとしています。再度、感謝します!
ダルド

@dardoこの本を読むことができます。(またはあなたの会社に見せてください;))すばらしい素晴らしい本:amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/…
Mik378

実際にこれをkindleで取得しました。 amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/...かなり良い今のところ= D
dardo

13

この議論が繰り返し起こると思う理由の1つは、必要なすべてのデータを持つオブジェクトを取得し、それと同一またはほぼ同一に見えるオブジェクトに変換することは深刻な苦痛のようだからですあなたは引き渡し中です。

それは本当です、それはピタです。しかし、そうすることにはいくつかの理由があります(上記に列挙されたものに加えて)。

  • ドメインオブジェクトは非常に重くなり、呼び出しに役に立たない情報が多く含まれることがあります。この膨張により、すべてのデータが送信、マーシャリング/アンマーシャリング、および解析されるため、UIの速度が低下します。FEにWebサービスを参照する多数のリンクがあり、AJAXまたは他のマルチスレッドアプローチで呼び出されることを考慮すると、UIがすぐに遅くなります。これはすべて、Webサービスの一般的なスケーラビリティに到達します。
  • 大量のデータを公開すると、セキュリティが簡単に侵害されます。DTOの結果からそれらを削除しない場合、少なくともユーザーのメールアドレスと電話番号を公開できます。
  • 実用上の考慮事項:1つのオブジェクトが永続ドメインオブジェクトとDTOとしてパレードするには、コードよりも多くのアノテーションが必要です。オブジェクトがレイヤーを通過する際のオブジェクトの状態の管理には、多くの問題があります。一般に、これは、管理するPITAに過ぎず、単にドメインオブジェクトからDTOにフィールドをコピーするという退屈な作業です。

ただし、変換ロジックをコンバータークラスのコレクションにカプセル化すると、かなり効果的に管理できます。

'convert(domainObj、toDto)'を実行できるlambdaJを見てください。コレクションで使用するためのオーバーロードがあります。これを使用するコントローラーメソッドの例を次に示します。ご覧のとおり、それほど悪くはありません。

    @GET
    @Path("/{id}/surveys")
    public RestaurantSurveys getSurveys(@PathParam("id") Restaurant restaurant, @QueryParam("from") DateTime from, @QueryParam("to") DateTime to) {

        checkDateRange(from, to);

        MultiValueMap<Survey, SurveySchedule> surveysToSchedules = getSurveyScheduling(restaurant, from, to);
        Collection<RestaurantSurveyDto> surveyDtos = convert(surveysToSchedules.entrySet(), SurveyToRestaurantSurveyDto.getInstance());
        return new RestaurantSurveys(restaurant.getId(), from, to, surveyDtos);

    }

入力に感謝し、私の考えは同じ線に沿っています=)
dardo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.