データ転送オブジェクトとは何ですか?


217

データ転送オブジェクトとは何ですか?

MVCにはモデルクラスDTOがあり、そうでない場合の違いは何ですか?両方が必要ですか?


@ yegor256とその記事のその本は、APIからデータを取得する方法と、DBにデータを格納する方法を知っているため、SRPに違反していますが、問題ありません。
Betlista

回答:


222

データ転送オブジェクトは、データをカプセル化し、アプリケーションのサブシステム間で送信するために使用されるオブジェクトです。

DTOは、N層アプリケーションのサービス層で最もよく使用され、それ自体とUI層の間でデータを転送します。ここでの主な利点は、分散アプリケーションでネットワークを介して送信する必要があるデータの量が減ることです。また、MVCパターンで優れたモデルを作成します。

DTOのもう1つの用途は、メソッド呼び出しのパラメーターをカプセル化することです。これは、メソッドが4つまたは5つを超えるパラメーターを取る場合に役立ちます。

DTOパターンを使用する場合は、DTOアセンブラも使用します。アセンブラは、ドメインオブジェクトからDTOを作成するために使用され、その逆も同様です。

ドメインオブジェクトからDTOへの変換とその逆の変換は、コストのかかるプロセスになる可能性があります。Martin Fowlerがここで説明するように、分散アプリケーションを作成していない場合は、パターンから大きなメリットが得られないでしょう。


7
「DTOはMVCパターンで優れたモデルを作成します」-ただし、モデルにオブジェクトのすべてのデータが含まれていて、DTOがデータの一部で最適化されている必要はありませんか モデルAがあり、それを2つのサブシステムに渡す必要がある場合、それぞれの関連フィールドを持つA_DTO_1とA_DTO_2がありますか?「メソッド呼び出しのパラメーターをカプセル化するためにDTOを使用することができます」->分散システムでなくても、パラメーターをラップするすべてのクラスはDTOですか?MVCのモデルはドメインオブジェクトではありませんか?
Yaron Naveh 2009年

2
あなたの最初の質問に答えて、私は同じことについて話しているとは思いません。MVCのモデルは、必ずしもドメインモデルのクラスである必要はありません。そうは言っても、それは十分に可能です。DTOを使用すると、不要なものがすべて取り除かれます。使用するアーキテクチャによって異なります。2番目の質問にどのように答えるかは正確にはわかりません。ネットワーク全体であるかどうかにかかわらず、それは(サブ)システム間で転送される一連のデータをカプセル化するオブジェクトであるため、DTOであると主張します。
ベニーハレット

12
「DTOのもう1つの用途は、メソッド呼び出しのパラメーターをカプセル化することです。これは、メソッドが4つまたは5つを超えるパラメーターを取る場合に役立ちます。」これは、実際にはポルターガイストまたはジプシーワゴンクラスと呼ばれるアンチパターンです。メソッドに4つの引数が必要な場合は、4を指定します。オブジェクトをメソッドまたはクラスに移動するためだけにクラスを作成しないでください。
Wix

2
@Wix、良い点。ただし、意味的に正しい場合は問題ないと思います(たとえば、プロパティ自体を値としてではなく、プロパティを持つ設定クラスを渡す場合)。あなたがすべきでないことは、単一のオブジェクトを渡すためにすべての引数を投入することです。それらは非常によく無関係であり、後で悪夢のもつれを解く可能性があるためです。
Aram Kocharyan 2012

3
DTOは、メソッド呼び出し(LocalDTOになる)のパラメーターをカプセル化するために使用しないでください。リモートインターフェイスのコンテキストで導入されました。martinfowler.com
Rui

28

DTOの定義は、Martin Fowlerのサイトにあります。DTOは、パラメーターをメソッドに転送するため、および戻り値の型として使用されます。多くの人々はUIでそれらを使用しますが、他の人々はそれらからドメインオブジェクトを膨らませます。


22

DTOはばかげたオブジェクトです。プロパティを保持し、ゲッターとセッターを持っていますが、(compare()またはequals()実装以外の)重要なロジックはありません。

通常、MVCのモデルクラス(ここでは.net MVCと想定)はDTO、またはDTOのコレクション/集合体です


3
あなたが説明しているのはLocalDTOです:martinfowler.com/bliki/LocalDTO.html
Rui

3
DTOのよ​​うなものを使用すると便利なケースの1つは、プレゼンテーションレイヤーのモデルと基になるドメインモデルの間に大きな不一致がある場合です。この場合、ドメインモデルからマップし、プレゼンテーションに便利なインターフェイスを提供するプレゼンテーション固有のファサード/ゲートウェイを作成することは理にかなっています。
阿弥陀

14

一般に、値オブジェクトは不変である必要があります。以下のような整数文字列は Javaでオブジェクト。これらを使用して、ソフトウェアレイヤー間でデータを転送できます。マイクロサービス環境やレガシーJavaエンタープライズアプリなど、さまざまなリモートノードでソフトウェアレイヤーまたはサービスが実行されている場合。2つのクラスのほぼ正確なコピーを作成する必要があります。ここがDTOに出会った場所です。

|-----------|                                                   |--------------|
| SERVICE 1 |--> Credentials DTO >--------> Credentials DTO >-- | AUTH SERVICE |
|-----------|                                                   |--------------|

レガシーJava Enterprise Systemsでは、DTOにさまざまなEJB要素を含めることができます。

これがベストプラクティスであるかどうかはわかりませんが、Spring MVC / Bootプロジェクトで個人的に次のようにValueオブジェクトを使用しています。

        |------------|         |------------------|                             |------------|
-> Form |            | -> Form |                  | -> Entity                   |            |
        | Controller |         | Service / Facade |                             | Repository |
<- View |            | <- View |                  | <- Entity / Projection View |            |
        |------------|         |------------------|                             |------------|

コントローラー層はエンティティが何であるかを知りません。フォームおよびビュー値オブジェクトと通信します。フォームオブジェクトにはJSR 303検証アノテーション(@NotNullなど)があり、ビュー値オブジェクトにはカスタムシリアル化のためのジャクソンアノテーションがあります。(たとえば、@ JsonIgnore)

サービス層は、エンティティオブジェクトを使用してリポジトリ層と通信します。Entityオブジェクトには、JPA / Hibernate / Spring Dataアノテーションが付いています。すべての層は下位層のみと通信します。循環/循環依存のため、層間通信は禁止されています。

User Service ----> XX CANNOT CALL XX ----> Order Service

一部のORMフレームワークには、追加のインターフェースまたはクラスを使用して投影する機能があります。そのため、リポジトリはViewオブジェクトを直接返すことができます。追加の変換は必要ありません。

たとえば、これはユーザーエンティティです。

@Entity
public final class User {
    private String id;
    private String firstname;
    private String lastname;
    private String phone;
    private String fax;
    private String address;
    // Accessors ...
}

ただし、id、firstname、lastnameのみを含む、ページ分割されたユーザーのリストを返す必要があります。次に、ORMプロジェクションのビュー値オブジェクトを作成できます。

public final class UserListItemView {
    private String id;
    private String firstname;
    private String lastname;
    // Accessors ...
}

リポジトリレイヤーからページ分割された結果を簡単に取得できます。Springのおかげで、投影にインターフェースのみを使用することもできます。

List<UserListItemView> find(Pageable pageable);

他の変換操作BeanUtils.copyメソッドがうまく機能することを心配しないでください。


11
  1. DTOとは何かという質問に対する私にとっての最良の答えは、DTO単純なオブジェクトであり、テストを必要とするビジネスロジックやメソッドの実装を含むべきではないということです
  2. 通常、モデル(MVCパターンを使用)はインテリジェントモデルであり、そのモデルにはさまざまな操作を実行する多くの/いくつかのメソッドを含めることができます(ビジネスロジックではなく、コントローラーで行う必要があります)。ただし、データを転送する場合(例:どこかからREST(GET/ POST/ whatever)エンドポイントを呼び出すか、SOAを使用してWebサービスを使用するなど)、必要のないコードで大きなサイズのオブジェクトを送信したくないエンドポイントはデータを消費し、転送を遅くします。

ビジネスロジックをコントローラーに含める必要があるのはなぜですか?
AlexioVay

6

MVCでは、データ転送オブジェクトは、ドメインモデルをより単純なオブジェクトにマッピングするためによく使用され、最終的にはビューによって表示されます。

ウィキペディアから:

以前は値オブジェクトまたはVOと呼ばれていたデータ転送オブジェクト(DTO)は、ソフトウェアアプリケーションサブシステム間でデータを転送するために使用される設計パターンです。DTOは、データベースからデータを取得するために、データアクセスオブジェクトと併用されることがよくあります。


3
値オブジェクトはDTOではありません。
coderpc

0

データ転送オブジェクト(DTO)は、「プロセス間でデータを運ぶオブジェクト」(Wikipedia)または「データをカプセル化し、アプリケーションの1つのサブシステムから別のサブシステムに送信するために使用されるオブジェクト」(スタックオーバーフローの回答)を表します。


0

DefN

DTOはハードコードされたデータモデルです。すべてのフィールドがコンパイル時に認識されているため、厳密に型指定されたプロパティを介してアクセスされる、ハードコードされた生産プロセスによって処理されるデータレコードのモデリングの問題のみを解決します。

対照的に、動的モデルまたは「プロパティバッグ」は、実行時に生産プロセスが作成されるときのデータレコードのモデリングの問題を解決します。

Cvar

DTOはフィールドまたはプロパティでモデル化できますが、誰かがCvarと呼ばれる非常に便利なデータコンテナを発明しました。値への参照です。参照プロパティと呼ばれるものを使用してDTOをモデル化すると、ヒープメモリを共有するようにモジュールを構成して、共同で作業することができます。これにより、パラメーターの受け渡しとO2O通信がコードから完全に排除されます。つまり、参照プロパティを持つDTOを使用すると、コードでゼロカップリングを実現できます

    class Cvar { ... }

    class Cvar<T> : Cvar
    {
        public T Value { get; set; }
    }

    class MyDTO
    {
        public Cvar<int> X { get; set; }
        public Cvar<int> Y { get; set; }
        public Cvar<string> mutableString { get; set; } // >;)
    }

出典:http : //www.powersemantics.com/

動的DTOは、動的ソフトウェアに必要なコンポーネントです。動的プロセスをインスタンス化するための1つのコンパイラステップは、スクリプト内の各マシンを、スクリプトが定義する参照プロパティにバインドすることです。動的DTOは、Cvarをコレクションに追加することによって構築されます。

    // a dynamic DTO
    class CvarRegistry : Dictionary<string, Cvar> { }

競合

注:Wixはパラメーターを編成するためのDTOの使用を「アンチパターン」としてラベル付けしたため、私は権威ある意見を述べます。

    return View(model);  // MVC disagrees

私の協調アーキテクチャは、設計パターンを置き換えます。私のウェブ記事を参照してください。

パラメータは、スタックフレームマシンの即時制御を提供します。継続的な制御を使用するため、即時制御が不要な場合、モジュールにパラメーターは必要ありません。私のアーキテクチャには何もありません。マシン(メソッド)のインプロセス構成は、パラメーターが値タイプである場合、複雑さだけでなく値(パフォーマンス)も追加します。ただし、参照型パラメーターを使用すると、コンシューマーはキャッシュミスによってヒープから値を取得できます。したがって、参照プロパティを使用してコンシューマーを構成します。機械工学の事実:処理(コンポーネントの作成)自体が無駄であるため、パラメータへの依存は一種の事前最適化です。詳細については、私のWの記事を参照してください。http://www.powersemantics.com/w.html

Fowlerと会社は、他のアーキテクチャーを知っていた場合、分散アーキテクチャー以外のDTOの利点を理解するかもしれません。プログラマーは分散システムしか知りません。統合コラボレーティブシステム(別名、製造、別名、製造)は、私がこの方法でコードを記述した最初の人なので、自分のアーキテクチャとして主張しなければならないものです。

一部の人は、DTOを貧血ドメインモデルと見なします。つまり、DTOは機能を欠いていますが、これは、オブジェクトが相互作用するデータを所有する必要があることを前提としています。この概念モデルでは、オブジェクト間でデータを配信する必要があります。これは、分散処理のモデルです。ただし、製造ラインでは、各ステップは最終製品にアクセスして、所有または制御することなく変更できます。これが、分散処理と統合処理の違いです。製造は、製品を運用および物流から分離します。

電子メールの追跡を維持せずに相互に電子メールで作業する無駄なオフィスワーカーの集まりとしてのモデリング処理には、本質的に何も問題はありません。適切にモデル化された分散プロセスは、製品にどの操作が行われ、どの操作が行われるかを記述したドキュメント(アクティブルーティング)を添付します。アクティブなルーティングは、プロセスの開始前に書き込まれるプロセスのソースルーティングのコピーです。欠陥またはその他の緊急の変更が発生した場合、アクティブなルーティングは、送信先の操作ステップを含むように変更されます。これにより、生産に費やされたすべての労働力が明らかになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.