18

stackoverflow に関する Q/A をいくつか読んだ後でも、Web アプリケーションでの DTO の正しい実装についてまだ混乱しています。私の現在の実装は、(Java EE ベースの) 多層アーキテクチャ (永続性、サービス、およびプレゼンテーション レイヤーを含む) ですが、すべてのレイヤーで使用される "共通" パッケージを使用し、(とりわけ) ドメイン オブジェクトを含みます。この場合、レイヤーは実際には独立しているとは見なされません。共通パッケージを段階的に削除する予定ですが、さまざまな課題/質問に遭遇します。

  • パーシスタンス レイヤーがクラスmyproject.persistence.domain.UserEntity (JPA ベースのエンティティ) を使用して、データベースとの間でデータを格納およびロードするとします。ビューにデータを表示するには、別のクラスmyproject.service.domain.Userを提供します。どこで変換できますか? ユーザー向けのサービスは、2 つのクラス間の変換を担当しますか? これは本当に結合を改善するのに役立ちますか?
  • Userクラスはどのように見えるべきですか? 不変にするためにゲッターのみを含める必要がありますか?ビューが既存のユーザーを編集するのは面倒ではありませんか (新しいUserを作成する、既存のUserオブジェクトのゲッターを使用するなど)。
  • 同じ DTO クラス ( User ) を使用して、既存のユーザーを変更する/新しいユーザーを作成する要求をサービスに送信する必要がありますか、それとも他のクラスを実装する必要がありますか?
  • myproject.service.domain 内のすべての DTO を使用することで、プレゼンテーション レイヤーはサービス レイヤーに大きく依存していませんか?
  • 自分の例外を処理する方法は? 私の現在のアプローチでは、ほとんどの「重大な」例外は、プレゼンテーション レイヤーによって処理されるまで再スローされます (通常、例外はログに記録され、何か問題が発生したことがユーザーに通知されます)。一方では、共有パッケージを再び持っているという問題があります。一方、これが「ベストプラクティス」と見なせるかどうかはまだわかりません。何か案は?

回答ありがとうございます。

4

2 に答える 2

19

異なるレイヤーにいくつかのパッケージを配置することは珍しくありませんが、通常はロギングなどの分野横断的な問題のためにのみ行われます。モデルを異なるレイヤーで共有しないでください。モデルを変更すると、それらすべてのレイヤーで変更が必要になります。通常、モデルはデータ レイヤーに近い下位レイヤーです (アプローチに応じて、上、下、または絡み合っています)。

データ転送オブジェクトは、その名前が示すように、データ転送に使用される単純なクラスです。そのため、オブジェクトではなくメッセージを介して通信する SOA アーキテクチャがある場合は特に、レイヤー間の通信に通常使用されます。DTO は単に情報を変更するのではなく、転送する目的で存在するため、不変である必要があります。

ドメイン オブジェクトと DTO は別物であり、プレゼンテーション層で必要なオブジェクトは別物です。ただし、小規模なプロジェクトでは、これらのさまざまなセットをすべて実装し、それらの間で変換する労力に見合わない場合があります。それはあなたの要件に依存します。

あなたは Web アプリケーションを設計していますが、「Web アプリケーションをデスクトップ アプリケーションに切り替えることはできますか? 私のサービス層は私のプレゼンテーション ロジックを本当に認識していないのでしょうか?」これらの観点から考えると、より優れたアーキテクチャへと導かれます。

あなたの質問に:

パーシスタンス レイヤーがクラス myproject.persistence.domain.UserEntity (JPA ベースのエンティティ) を使用して、データベースとの間でデータを格納およびロードするとします。ビューにデータを表示するには、別のクラス myproject.service.domain.User を提供します。どこで変換できますか? ユーザー向けのサービスは、2 つのクラス間の変換を担当しますか? これは本当に結合を改善するのに役立ちますか?

サービス層は、そのクラス (DTO) とその下の層 (持続性としましょう) を認識しています。そうです、サービスは永続性とそれ自体の間の変換を担当します。

User クラスはどのように見えるべきですか? 不変にするためにゲッターのみを含める必要がありますか?ビューが既存のユーザーを編集するのは面倒ではありませんか (新しいユーザーを作成する、既存のユーザー オブジェクトのゲッターを使用するなど)。

DTO の背後にある考え方は、DTO は転送のみに使用するため、新しいユーザーの作成などの操作は必要ありません。そのためには、さまざまなオブジェクトが必要です。

同じ DTO クラス (ユーザー) を使用して、既存のユーザーを変更する/新しいユーザーを作成する要求をサービスに送信する必要がありますか、それとも他のクラスを実装する必要がありますか?

サービス メソッドは操作を表す場合があり、DTO はデータのみを含むパラメーターです。別のオプションは、操作を表し、DTO を含むコマンドを使用することです。これは、サービスが単なるコマンド プロセッサである SOA アーキテクチャで一般的です。たとえば、(コマンドごとに 1 つの操作を行うのではなく) パラメーターとしてインターフェイスを使用する 1 つのExecute操作を行います。ICommand

myproject.service.domain 内のすべての DTO を使用することで、プレゼンテーション層はサービス層に大きく依存していませんか?

はい、サービス層の上の層はそれに依存します。それがアイデアです。利点は、そのレイヤーのみがそれに依存することであり、上位レイヤーも下位レイヤーも存在しないため、変更はそのレイヤーにのみ影響します (すべてのレイヤーからドメイン クラスを使用した場合とは異なります)。

自分の例外を処理する方法は? 私の現在のアプローチでは、ほとんどの「重大な」例外は、プレゼンテーション レイヤーによって処理されるまで再スローされます (通常、例外はログに記録され、何か問題が発生したことがユーザーに通知されます)。一方では、共有パッケージを再び持っているという問題があります。一方、これが「ベストプラクティス」と見なされるかどうかはまだわかりません。何か案は?

各レイヤーには独自の例外があります。それらは、次の種類の例外にカプセル化されて、あるレイヤーから別のレイヤーに流れます。場合によっては、何らかの処理 (たとえば、ロギング) を行う 1 つのレイヤーによって処理され、上位レイヤーが処理する必要がある別の例外をスローすることがあります。また、それらが処理され、問題が解決される場合もあります。たとえば、データベースへの接続の問題を考えてみてください。例外がスローされます。あなたはそれを処理し、1 秒後に再試行することを決定することができ、その後成功する可能性があるため、例外は上に流れません。再試行も失敗すると、例外が再スローされ、ユーザーに適切に通知して層を再試行するように依頼するプレゼンテーション層まで流れます。

于 2014-04-26T08:28:58.787 に答える