データ転送オブジェクト(DTO)がアンチパターンなのはなぜですか?


132

私は最近、データ転送オブジェクト(DTO)はアンチパターンであると言う人を耳にしました。

どうして?代替案は何ですか?


11
おそらく、ビジネスオブジェクト自体が独自のデータを転送できるため、どうもありがとうございます。
Zoidberg

13
「アンチパターン」は、「15分前に長いフレーズ」の候補になりそうです。「それはよく知られている...」のように、今では「自分の考えを正当化することを気にしない」の同義語です
クレイグ・スタンツ2009

6
Zoidbergは、メソッドを使用してオブジェクトをネットワーク経由で送信することで、CORBA、DCOM、および私の記憶を消去しようとする他の体験を提供してくれました。問題は、遅かれ早かれこれらのメソッドを呼び出したいということです。
Craig Stuntz

10
DTOはDRYの原則を具体化してます。これは残念ながらJ2EEでは自分自身を繰り返します。
joeforker 2009

これを読むとよいでしょう:データ転送オブジェクトは恥です
yegor256

回答:


139

すべてのデータが2度あるプロジェクトもあります。1回はドメインオブジェクトとして、もう1回はデータ転送オブジェクトとして。

この複製には莫大なコストがかかるため、アーキテクチャはこの分離から大きな利益を得る必要があります。


5
「莫大なコスト」について詳しく教えてください。また、コード生成技術を使用してDTOクラスを生成してもコストを削減できない理由を説明してください。
ジョンサンダース

70
+1。二回?あなたが幸運である場合のみ:-) DTOとしてドメインエンティティを複製するプロジェクトは、それらを補完するためにほぼ同じですが、非常に微妙に異なるUI Beanを使用する傾向があります。それは3だと神禁止し、あれば、上に行く(Webサービス/ XML-RPC /何でも)をリモーティングのいくつかの並べ替えがあります、あなたは簡単に4または5に取得することができます
ChssPly76

17
私は現在、企業向けの14層ラザニアアーキテクチャを使用しています(KIDDINGではありません)。主にデータトランスレーター用の11層ほどが無料で提供されないことは間違いありません。
KarlP 2009

10
また、私は愚かなデザインを扱うときにコードジェネレーターが大好きですが、それらはa)初めから間違っていることは確かです。b)彼らは無料で来ません。
KarlP 2009

7
申し訳ありませんが、これは単に正しくないため、間違った答えが高く評価され、受け入れられました。まず第一に、リフレクションを使用してオンザフライでDTOを生成できます。次に、CASEシステムやoAWなどで「ルート定義」を使用して、BOとDTOを生成できます。第三に、XSDとJAXBを使用してDTOを生成し、BOのベースとしてDTOを使用できます。または、いずれにせよ、DBから新たにフェッチされたEJBをあえて転送する場合は、XSDから両方を生成できます。クライアントプログラムへの
ワイヤリング

128

DTOはアンチパターンではありません。ワイヤーを介して(たとえば、Ajax呼び出しのWebページに)データを送信する場合、宛先が使用するデータのみを送信することで帯域幅を節約する必要があります。また、多くの場合、プレゼンテーションレイヤーは、ネイティブビジネスオブジェクトとは少し異なる形式のデータを持っていると便利です。

これはJava指向の質問であることは知っていますが、.NET言語では匿名型、シリアル化、およびLINQにより、DTOをオンザフライで構築できるため、DTOを使用するためのセットアップとオーバーヘッドが削減されます。


15
@ジョン、これは間違いです。私はいつもそれをします。シリアライゼーションはリフレクションを使用しますが、これは匿名型でうまく機能します。オブジェクトとしてシリアライザに渡すだけです。そして、それが(例えば、xmlやjsonに)シリアライズされたら、もちろんメソッドから返すことができます。
Gabe Moothart、2009

8
ええと、ジョン、それは真実ではありません。匿名型をJSONにシリアル化できます。MVCアプリで試してみてください:return Json(new {Foo = "Hi there!});私はそれがうまく機能することを約束します。おそらく、匿名型はオブジェクトグラフに循環がないため、おそらく非匿名型よりも優れています。 、JSON
シリアライザーを壊し

1
この意味で、Jsonのシリアル化はDTOではないため、適用されません。そしてもちろん、上記の私の主張も当てはまります。
ジムバローズ

1
Gabeは正解です。データの重複がない場合、DTO自体はアンチパターンではありません(ただし、誤って使用した場合でも可能です)。たとえば、BOはさまざまなソースからのデータをDTOに集約できます。
アストロアワー

3
+1。また、帯域幅の節約以外にも、DTOが必要な理由はたくさんあります。(会社のポリシーまたは法律により)すべてのフィールドをネットワーク経由で送信することを許可されていますか?また、私たちの会社では、DAOはこれらのすべての最適化を行う必要があるため、非常に複雑です-サービスレイヤーで動作しているので、DTOを使用していて、オブジェクトXの関係について心配する必要がありません。他のn対nテーブルに。
user64141 14

25

EJB 3.0のAntiPatternのDTOは次のように述べています。

EJB 3.0より前のEJB仕様におけるエンティティBeanの重い性質により、データ転送オブジェクト(DTO)などの設計パターンが使用されていました。DTOは軽量のオブジェクトになり(そもそもエンティティBean自体である必要がありました)、層を越えてデータを送信するために使用されます...現在のEJB 3.0仕様では、エンティティBeanモデルがプレーンな古いJavaオブジェクト(POJO)と同じになっています。この新しいPOJOモデルを使用すると、エンティティごとまたはエンティティのセットごとにDTOを作成する必要がなくなります。層全体にEJB 3.0エンティティを送信する場合は、java.io.Serialiazableを実装するだけです。


6
同じJVM内のメソッド間でメモリ内のオブジェクトを転送する場合はtrue。回線上で実際にシリアル化していて、シリアル化の深さを制御したり、遅延読み込みを保持したりする場合は当てはまりません。
wrschneider

はい、同じJVMであっても、JEE / Springトランザクション管理を使用する場合は、同じtheadにとどまるように注意する必要があります。
2014

20

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を使用)が原因で発生しました。Springなどのフレームワークに基づく最近のほとんどのJavaシステムは、POJOをドメインオブジェクト(JPAなどで注釈が付けられていることが多い)として単一層で使用する代替の簡略化されたビューを採用しています...ここでのDTOの使用は不要です。


3
DTO が適切なコンテキストで使用される場合、アンチパターンではなく、適切なパターンであることは完全に正しいことです。あなたの2番目のリンクは現在死んでいるように見えますが、私が見た最大の悪用は、すべてのドメインオブジェクトがデータベースの相互作用に対応する「DTO」を持っていて、値を追加せず、DTOではなかったことです。
デビッド

19

オブジェクト指向の純粋主義者は、オブジェクトが実際のドメインオブジェクトではなくデータテーブル表現になるため、DTOはアンチパターンであると言います。


9

一部の人は、悪用の可能性があるため、DTOをアンチパターンと見なしています。彼らはしばしばそうするべきではない/する必要がないときに使用されます。

この記事では、いくつかの乱用について漠然と説明しています。


1
この記事では、DTOが悪用される可能性のあるパターンとしてより正確に説明されています。
Craig Stuntz

これはリンクのみの回答に相当し、実際には少なくとも記事からの引用が必要です。これがどうしてNot An Answerのフラグを立てられなかったのかわかりません。
Nathan Hughes


7

分散システムを構築している場合、DTOは反パターンではありません。誰もがそういう意味で開発するわけではありませんが、(たとえば)Open Socialアプリがあれば、すべてJavaScriptで実行されます。

APIに大量のデータを送信します。次に、これは何らかの形式のオブジェクト(通常はDTO / Requestオブジェクト)に逆シリアル化されます。これを検証して、入力したデータが正しいことを確認してから、モデルオブジェクトに変換できます。

私の意見では、誤用されているため、アンチパターンと見なされています。分散システムを構築していない場合は、それらを必要としない可能性があります。


4

意図データ転送オブジェクトは、異なるソースからのデータを格納し、データベース(またはにそれを転送することで、リモート・ファサード一度)。

ただし、DTOはデータを格納するだけでなく、データベース/ファサードとの間で転送するため、DTOパターンは単一責任の原則に違反しています。

データベースレイヤー分離する必要があるため、データオブジェクトをビジネスオブジェクトから分離する必要はありません。とにかくん。

DTOの代わりに、オブジェクトのコレクション(Aggregate)とデータ転送(Repository)を分離するAggregate and Repository Patternsを使用する必要があります)。

オブジェクトのグループを転送するには、リポジトリのセットとトランザクションコンテキストを保持する作業単位パターンを使用できます。トランザクション内で集約内の各オブジェクトを個別に転送するため。


4

すべてのドメインオブジェクトに関連付けられたオブジェクトをすばやくロードする場合、DTOはANTI-PATTERNではなく必要になります。

DTOを作成しないと、ビジネスレイヤーからクライアント/ Webレイヤーに不要なオブジェクトが転送されます。

この場合のオーバーヘッドを制限するには、DTOを転送します。


1

質問は「なぜ」ではなく、「いつ」である必要があります。

明らかに、それを使用した結果だけがより高いコストである場合、それはアンチパターンです(ランタイムまたはメンテナンス)。私は、データベースエンティティクラスと同一の何百ものDTOを持つプロジェクトに取り組みました。単一のフィールドを追加するたびに、DTOに、エンティティに、DTOからドメインクラスまたはエンティティへの変換、逆変換など、IDを4回追加します。いくつかの場所とデータを忘れました矛盾。

ドメインクラスの異なる表現が本当に必要な場合、それはアンチパターンではありません -よりフラットに、より豊かな、より狭いです、...

個人的には、ドメインクラスから始めて、適切な場所で適切にチェックして、それを渡します。「ヘルパー」クラスに注釈を付けたり追加したりして、マッピングを作成したり、データベースや、JSONやXMLなどのシリアル化形式に追加したりできます。必要に応じて、クラスを常に2つに分割できます。

それはあなたの視点についてです-私はドメインオブジェクトを、互いに作成された複数のオブジェクトではなく、さまざまな役割を果たす単一のオブジェクトとして見ることを好みます。オブジェクトの唯一の役割がデータの転送である場合、それはDTOです。


1

すべてのリモートオブジェクトをDTOとして実装する場合、それはアンチパターンになる可能性があると人々は言っていると思います。DTOは単なる属性のセットにすぎず、大きなオブジェクトがある場合は、それらを必要としない、または使用しない場合でも、常にすべての属性を転送します。後者の場合、プロキシパターンの使用を優先します。

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