データ転送オブジェクト (DTO)はアンチパターンであると言っている人を最近耳にしました。
どうして?代替手段は何ですか?
一部のプロジェクトにはすべてのデータが2回ある。ドメインオブジェクトとして1回、データ転送オブジェクトとして1回。
これは複製には莫大なコストがかかりますであるため、アーキテクチャはこの分離から大きな利益を得る必要があります。
DTOはアンチパターンではありません。ワイヤーを介して(たとえば、Ajax呼び出しのWebページに)データを送信する場合、宛先が使用するデータのみを送信することで帯域幅を確実に節約する必要があります。また、多くの場合、プレゼンテーション層がネイティブのビジネスオブジェクトとは少し異なる形式のデータを持っていると便利です。
これはJava指向の質問であることは知っていますが、.NET言語では、匿名型、シリアル化、およびLINQによりDTOをオンザフライで構築できるため、セットアップと使用時のオーバーヘッドが削減されます。
EJB 3.0のAntiPatternのDTO 言います:
EJB 3.0より前のEJB仕様におけるエンティティBeanの重い性質により、データ転送オブジェクト(DTO)などの設計パターンが使用されていました。 DTOは軽量オブジェクトになり(最初はエンティティBean自体であるはずでした)、階層間でデータを送信するために使用されていました...現在、EJB 3.0仕様は、Entity BeanモデルをPlain old Javaオブジェクト(POJO)。この新しいPOJOモデルを使用すると、エンティティごとまたはエンティティのセットごとにDTOを作成する必要がなくなります。EJB3.0エンティティを層全体に送信する場合は、それらを作成します。 Java.io.Serialiazableを実装するだけです
DTO自体はアンチパターンではないと思いますが、DTOの使用に関連するアンチパターンがあります。ビル・ダドニーは、例としてDTO爆発について言及しています。
http://www.softwaresummit.com/2003/speakers/DudneyJ2EEAntiPatterns.pdf
ここに記載されているDTOの不正使用も多数あります。
http://anirudhvyas.com/root/2008/04/19/abuses-of-dto-pattern-in-Java-world/
これらは、階層間でデータを渡す手段として3層システム(通常はテクノロジーとしてEJBを使用)が原因で発生しました。最新のJava Springなどのフレームワークに基づくシステムは、単一の層でドメインオブジェクト(多くの場合、JPAなどで注釈が付けられます)としてPOJOを使用する代替の簡易ビューを取ります...ここのDTOは不要です。
オブジェクト指向の純粋主義者は、オブジェクトが実際のドメインオブジェクトではなくデータテーブル表現になるため、DTOはアンチパターンであると言うでしょう。
乱用の可能性があるため、DTOはアンチパターンであると考える人もいます。あるべきでない/そうする必要がないときによく使われます。
この記事 いくつかの悪用について漠然と説明しています。
分散システムを構築している場合、DTOは確かにアンチパターンではありません。すべての人がその意味で開発されるわけではありませんが、(たとえば)Open SocialアプリがすべてJavaScriptで実行されている場合です。
APIに大量のデータを投稿します。次に、これは何らかの形式のオブジェクト(通常はDTO/Requestオブジェクト)に逆シリアル化されます。次に、これを検証して、入力されたデータが正しいことを確認してから、モデルオブジェクトに変換します。
私の意見では、誤用されているため、アンチパターンと見なされています。分散システムを構築していない場合、おそらく必要ないでしょう。
すべてのドメインオブジェクトに関連オブジェクトをEAGERlyでロードさせると、DTOはアンチパターンではなく必要になります。
DTOを作成しない場合、ビジネス層からクライアント/ Web層に不要なオブジェクトが転送されます。
この場合のオーバーヘッドを制限するには、DTOを転送します。
データ転送オブジェクト の目的は、さまざまなソースからのデータを保存し、それをデータベース(または リモートファサード )に一度に転送することです。
ただし、DTOパターンは Single Responsibility Principleに違反します。これは、DTOがデータを保存するだけでなく、データベース/ファサードに。
データオブジェクトをビジネスオブジェクトから分離する必要は、アンチパターンではありません。とにかく データベースレイヤーを分離する が必要になるからです。
DTOの代わりに、オブジェクトのコレクション( Aggregate )とデータ転送( Repository )を分離する集約パターンとリポジトリパターンを使用する必要があります。
オブジェクトのグループを転送するには、リポジトリのセットとトランザクションコンテキストを保持する 作業単位 パターンを使用できます。トランザクション内で集約内の各オブジェクトを個別に転送するため。
質問は「理由」ではなく、「when」にする必要があります。
間違いなく、それはそれを使用した結果のみがコストが高い場合のアンチパターン-ランタイムまたはメンテナンスです。データベースエンティティクラスと同じ数百のDTOを持つプロジェクトに取り組みました。 1つのフィールドを追加するたびに、4回のようにidを追加します-DTO、エンティティ、DTOからドメインクラスまたはエンティティへの変換、逆変換、...取得した場所とデータの一部を忘れました一貫性がありません。
ドメインクラスの異なる表現が本当に必要な場合はアンチパターンではありません-よりフラットで、よりリッチで、より狭い...
個人的には、ドメインクラスから始めて、適切な場所で適切なチェックを行って渡します。 JSONやXMLなどのシリアル化形式にマッピングするための「ヘルパー」クラスに注釈を付けたり、追加したりできます。必要に応じて、クラスをいつでも2つに分割できます。
それはあなたの視点についてです-ドメインオブジェクトを、互いに作成された複数のオブジェクトではなく、さまざまな役割を果たしている単一のオブジェクトとして見ることを好みます。オブジェクトが持つ唯一の役割がデータの転送である場合、それはDTOです。
すべてのリモートオブジェクトをDTOとして実装すると、アンチパターンになる可能性があると人々は考えていると思います。 DTOは単なる属性のセットであり、大きなオブジェクトがある場合は、必要としないか使用していなくても、すべての属性を常に転送します。後者の場合、プロキシパターンを使用することをお勧めします。