2017-04-10 9 views
3

いくつかのコードをリファクタリングしようとしています。 DTOオブジェクトを作成するいくつかのクラスがあります。これらのクラスは、サービスレイヤのパスであり、後で@RestControllerによって返されます。私が知っているように、コントローラでのみデータ転送オブジェクトを構築し、ビューに渡すのが最善です。特に、取得値と設定値でWrapperDTO<T>のようなものを使用すると便利です。おそらく、複雑なオブジェクトや単純なデータ型を持つWrapperDTOを構築するときに違いがあるかもしれません。すべての意見が高く評価されます。データ転送オブジェクトDTOビルド

+0

私はあなたが【こちら】(https://softwareengineering.stackexchange.com/questions/277817/what-is-the-best-way-to-create-dtos-from-entities-and-を見てすべきだと思いますupdate-entities-from-dtos) –

答えて

5

DTOは、アプリケーションの異なるレイヤー間でデータを転送するために使用できます:DAO、Service、Facade、Controller。私の経験では、DTOは説得力のある話題です。

私の意見では、変換が遅いほど、変換が必要ない場合はさらに優れています。一般に、後者はアプリケーション境界にあります。 DTOは無料ではなく、マッピングとそのサポートが必要です。したがって、DTOは、ドメインモデルの不一致またはモデルの技術的不一致が境界にある場合に意味をなされます。詳細については、LocalDTO article and the associated linkをご覧ください。

私はサービスに焦点を当てている場合 - >コントローラ層 - >ファサード:彼らはサービスのことをやっているし、彼らは彼らの処理を行うためにお互いを呼び出すことができ:

  • サービス。あなたのドメインモデルがサービス境界を越えて一貫しているならば、service => facadeは結果をDTOに変換するのは時期尚早です。

  • ファサード:サービスを編成して入出力を変換することがあります。私の視点では、DTOとの間で変換するのが適切な場所になります。しかし、それが必要な場合のみ。あなたのドメインモデルは、この境界(フィルタリングフィールド、集約...)を超えて変換されなければならないからです。彼らの論理は単純で境界論理に還元されている。ファサードとコントローラとの関係は、通常one <-> oneです。 ***

    マージファサードとコントローラ通常意味をなさない


このように私の視点では、あなたの最初の提案は、より適応例です。 UserController....。最も重要なのは、実用的なままにすることです。

+1

素敵でバランスのとれた答えです。私はDTOとドメインオブジェクトに関する2つの記事を書いており、主に同じ結論を出しました。 https://notesofapragmaticprogrammer.wordpress.com –

2

サービス層でDTOを作成する方がよいでしょう。

コントローラはビ​​ジネスロジックの詳細を知ってはいけません。例えば。ユーザー情報を返す必要がありますが、一部のフィールド(パスワードなど)を除外する必要があります。フィールドはUserエンティティに存在しますが、DTOから削除する必要があります。

コントローラーでSomePaginationDTOを取得しましたが、フィルタを解析したり、並べ替えを適用したり、結果を制限するなどのサービスにDTOを渡す必要があります。すべてのロジックはサービスの責任の一部です。だから私はSomePaginationDTOをサービスに渡すでしょう。

+1

私は考えが混ざっています。私はSomePaginationDTOについて完全に同意します。私は動的DTO(マップ)を使用し、サービスに(「ソート、フィルタ、ページング」と同様の方法で)「一部のフィールドのみ」を依頼することさえできます。私が 'user-no-password'を望むなら、私はこのメカニズムを使用します。代わりに、コントローラのサービスからEntity(または完全なDTO)を取得し、コントローラに「パスワードなしで(動的)」を作成します。フィールド選択の仕組みがない場合、サービスでgetUserNoPassword()メソッドを作成しないと、私はコントローラのDTOへの変換を行います。私はこれがビジネスロジックであるかどうかはわかりません。私が間違っている ? –

+0

私の場合、コントローラはデータの制限方法や返されるデータの量を知るべきではありません。それはサービスIMHOの一部です。コントローラの責任は、データ転送(マーシャルアンマーシャル)、セキュリティチェック、フィルタリング、エラー処理です。 – StanislavL

+0

ありがとうございます。しかし、サービスで列の選択が実装されていない場合は、あるいは、サービスがソートやページングを実装していない場合は、メモリ内のソートやページングは​​どこで行いますか?コントローラーでやっているのと同じように、サービスでサポートされていないときはプロパティ/列の選択を行います。これは、UI機能のみ、場合によってはユーザごとの好みであってもよい。私は本当にこれについての意見を聞きたい。 –

0

これを行うための正式な方法はありません。それは、DTOが何のために使用されているかによって異なります。 サービスレベルにクライアントが1つしかない場合は、DTOをサービスレベルで使用します。この場合、サービスレベルでDTOを使用する場所はどこですか?2つ以上のクライアントがある場合、サービスレベルでDTOを使用しないほうがよいでしょう。

は私が詳細にこれを説明してみましょう:

基本的には、サービスレベルにDTOを含まないがより努力が必要であることは明らかです。したがって、クライアントが1つしかない場合、私は物事を単純に保ち、DTOをサービスメソッドの戻り値の型として使用します。

サービスのクライアントが複数存在する場合、クライアントは異なるDTOを必要とします(たとえば、オブジェクトの表現はjsoncsvです)。そのような場合、私はサービスからDTOを返さない。それ以外の場合は、DTOごとに異なるサービスや異なるサービス方法などが必要です。サービスレベルでDTOを使用しない場合は、コントローラレベル。私はまだコントローラのレベルはできるだけシンプルでなければならないと考えています。コントローラーとサービスの間に中間的な変換レベルがあるかもしれません - 不快ですが、いくつかのサービスを持つ方がはるかに優れています。

-1

私は他の質問の一部として素晴らしい答えを見つけました。もちろん、この/私の答えは賞金には参加しません。今日は物事がどのように実装されているかを説明するインスピレーションだけです。だから見てください:

  • モデルクラス。彼らはすべてのゲッター/セッターを手に入れません。 はモデルロジックに依存します。そうでなければ、容易に が一貫性を破ることができるモデルを得る。あるいは、多くの自明なものがあります。 にUser.registrationDateフィールドがあるとします。新しいユーザー オブジェクトを作成するときは、ハンドでregistrationDateフィールドにフィールドすることを忘れないようにしてください。だから、あなたの コンストラクタにregistrationDate初期化を置き、setterを削除するだけです!
  • モデル内のリポジトリインタフェース。既存のストアドオブジェクトに依存するビジネスロジックがあるとします( )。 expliciltlyドメイン論理からインフラストラクチャ JPA、Hibernate、JDBCなどの依存関係を参照することはできません。このようにして、 オブジェクトをインターフェイスから照会します。
  • ビジネスサービス(オプション)。彼らはいくつかの複雑なロジック、多くの異なるエンティティを含む を実装します。セキュリティは含まず、 トランザクション管理も実装しています。あなたの質問はそれについてです。はい、ドメインロジックのエンティティのクエリを する必要がある場合は、クエリをリポジトリ に配置し、ビジネスサービスから呼び出します。
  • インフラストラクチャパッケージ内のリポジトリ実装。 JPAまたはmockitoなどを使用して リポジトリインタフェースを実装します。また、 には、セキュリティとトランザクションの両方が含まれていません。
  • アプリケーションサービス(オプション)。インフラストラクチャまたはセキュリティのチェックとの複合体がある場合は
  • リモートファサードインターフェイス。クライアントとサーバーは、 リモートファサードインターフェイス経由でのみ通信します。
  • リモートファサード実装(コントローラ)。太い実体 のオブジェクトを薄いDTO(データ転送オブジェクト)に変換します。すべてのトランザクション 境界設定とセキュリティはここにあります(注釈を使用することが多い)。

あなたはそのデザインについてどう思いますか?それはよく知っている春のMVCに適用されますか?

関連する問題