最近、データ転送オブジェクト(DTO)はアンチパターンだと言う人を耳にしました。
なんで?選択肢は何ですか?
最近、データ転送オブジェクト(DTO)はアンチパターンだと言う人を耳にしました。
なんで?選択肢は何ですか?
一部のプロジェクトには、すべてのデータが2回あります。1回はドメインオブジェクトとして、もう1回はデータ転送オブジェクトとして。
この複製には莫大なコストがかかるため、アーキテクチャは、この分離から大きな利益を得る必要があります。
DTOはアンチパターンではありません。回線を介して(たとえば、Ajax呼び出しのWebページに)データを送信する場合は、宛先が使用するデータのみを送信することで帯域幅を節約する必要があります。また、多くの場合、プレゼンテーション層では、ネイティブのビジネスオブジェクトとはわずかに異なる形式のデータを使用すると便利です。
これがJava指向の質問であることは知っていますが、.NET言語では、匿名型、シリアル化、およびLINQにより、DTOをオンザフライで構築できるため、DTOを使用する際のセットアップとオーバーヘッドが削減されます。
EJB3.0のアンチパターンのDTOは次のように述べています。
EJB 3.0より前のEJB仕様ではエンティティBeanの重みが大きいため、データ転送オブジェクト(DTO)などのデザインパターンが使用されていました。DTOは、階層間でデータを送信するために使用される軽量オブジェクト(そもそもエンティティBean自体である必要があります)になりました...現在、EJB 3.0仕様により、エンティティBeanモデルはPlain Old Java Object(POJO)と同じになります。この新しいPOJOモデルを使用すると、エンティティごとまたはエンティティのセットに対してDTOを作成する必要がなくなります...層全体にEJB 3.0エンティティを送信する場合は、java.io.Serialiazableを実装するだけです。
OOの純粋主義者は、オブジェクトが実際のドメインオブジェクトではなくデータテーブル表現になるため、DTOはアンチパターンであると言うでしょう。
DTO自体はアンチパターンではないと思いますが、DTOの使用に関連するアンチパターンがあります。Bill Dudneyは、例として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の使用は不要です。
乱用の可能性があるため、DTOをアンチパターンと見なす人もいます。それらは、あるべきではない/ある必要がないときによく使用されます。
この記事では、いくつかの悪用について漠然と説明しています。
分散システムを構築している場合、DTOは確かにアンチパターンではありません。誰もがその意味で開発するわけではありませんが、(たとえば)OpenSocialアプリがすべてJavaScriptで実行されている場合。
大量のデータをAPIに送信します。次に、これは何らかの形式のオブジェクト、通常はDTO/Requestオブジェクトに逆シリアル化されます。次に、これを検証して、モデルオブジェクトに変換する前に、入力したデータが正しいことを確認できます。
私の意見では、誤用されているため、アンチパターンと見なされています。分散システムを構築していない場合は、分散システムが必要ない可能性があります。
すべてのドメインオブジェクトに関連オブジェクトを熱心にロードさせる場合、DTOは必要になり、アンチパターンではありません。
DTOを作成しないと、ビジネスレイヤーからクライアント/Webレイヤーに不要なオブジェクトが転送されます。
この場合のオーバーヘッドを制限するには、DTOを転送します。
問題は「なぜ」ではなく、「いつ」であるべきです。
実行時やメンテナンスなど、使用した結果だけがコストが高くなる場合は、間違いなくアンチパターンになります。私は、データベースエンティティクラスと同一の何百ものDTOを持つプロジェクトに取り組みました。単一のフィールドを追加するたびに、4回のようにIDを追加します-DTO、エンティティ、DTOからドメインクラスまたはエンティティへの変換、逆変換、...いくつかの場所とデータを忘れました一貫性がありません。
ドメインクラスのさまざまな表現が本当に必要な場合、これはアンチパターンではありません-よりフラットで、よりリッチで、よりナローで、...
個人的には、ドメインクラスから始めて、適切な場所で適切にチェックしながら、それを渡します。いくつかの「ヘルパー」クラスに注釈を付けたり、追加したりして、マッピング、データベース、JSONやXMLなどのシリアル化形式にマッピングできます。必要に応じて、クラスをいつでも2つに分割できます。
それはあなたの視点についてです-私はドメインオブジェクトを、互いに作成された複数のオブジェクトではなく、さまざまな役割を果たしている単一のオブジェクトとして見ることを好みます。オブジェクトが持つ唯一の役割がデータの転送である場合、それはDTOです。
すべてのリモートオブジェクトをDTOとして実装すると、アンチパターンになる可能性があることを人々は意味していると思います。DTOは単なる属性のセットであり、大きなオブジェクトがある場合は、それらを必要としない、または使用しない場合でも、常にすべての属性を転送します。後者の場合、プロキシパターンを使用することをお勧めします。
データ転送オブジェクトの目的は、さまざまなソースからのデータを保存し、それをデータベース(またはリモートファサード)に一度に転送することです。
ただし、DTOはデータを格納するだけでなく、データベース/ファサードとの間でデータを転送するため、DTOパターンは単一責任の原則に違反します。
とにかくデータベース層を分離する必要があるため、データオブジェクトをビジネスオブジェクトから分離する必要性はアンチパターンではありません。
DTOの代わりに、オブジェクトのコレクション( Aggregate)とデータ転送(Repository )を分離するAggregateおよびRepositoryPatternsを使用する必要があります。
オブジェクトのグループを転送するには、一連のリポジトリとトランザクションコンテキストを保持するUnitOfWorkパターンを使用できます。トランザクション内で集約内の各オブジェクトを個別に転送するため。