REST API-DTOかどうか?[閉まっている]


154

現在プロジェクトのREST-APIを作成しており、ベストプラクティスに関する記事を読んでいます。多くの人はDTOに反対しているようで、単にドメインモデルを公開しているようですが、他の人はDTO(またはユーザーモデルなど、呼びたいもの)は悪い習慣だと考えているようです。個人的には、この記事は非常に理にかなっていると思いました。

ただし、すべての追加のマッピングコード、DTOの対応物と100%一致する可能性のあるドメインモデルなど、DTOの欠点も理解しています。

私たちのAPIは、他のクライアントがデータを消費できるように作成されていますが、適切に実行した場合は、可能であれば独自のWeb GUIにも使用したいと思います。

問題は、すべてのドメインデータを他のクライアントユーザーに公開したくない場合があることです。データの多くは、私たち自身のWebアプリケーションでのみ意味があります。また、すべてのシナリオでオブジェクトに関するすべてのデータ、特に他のオブジェクトとの関係などを公開したくない場合もあります。たとえば、特定のオブジェクトのリストを公開する場合、必ずしもオブジェクト階層全体を公開する必要はありません。そのため、オブジェクトの子は公開されませんが、リンク(ハテオア)を通じて発見できます。

この問題を解決するにはどうすればよいですか?ドメインモデルでジャクソンミックスインを使用して、さまざまなシナリオで公開されるデータを制御することを考えていました。それとも、DTOをずっと使用するべきでしょうか?欠点や論争があるとしても?


9
この質問が閉じても驚かないでください。これはディスカッションベースの質問で、明確な正解はありません。別の人に尋ねると、別の答えが得られます。
Ben Thurley 2016年

2
その記事のリンク(ibm.com/developerworks/community/blogs/barcia/entry/…)は壊れています。
pinkpanther 2017年

7
@pinkpantherそれは素晴らしい記事であり、もう利用できなくなって残念です。これがWeb Archiveキャッシュバージョンです。
cassiomolin 2017年

回答:


251

REST APIでDTOを使用する理由

DTOD ata T ransfer O bjectの略です。

このパターンは、非常に明確に定義された目的で作成されました:Webサービスのように、リモートインターフェースデータを転送します。このパターンはREST APIに非常によく適合しており、DTOを使用すると長期的に柔軟性が向上します。

アプリケーションのドメインを表すモデルと、APIによって処理されるデータを表すモデルは、異なる懸念事項であり(少なくともそうである必要があります)、互いに分離する必要があります。アプリケーションドメインモデルからフィールドを追加、削除、または名前を変更するときにAPIクライアントを壊したくない場合。

サービスレイヤーはドメイン/永続性モデルで動作しますが、APIコントローラーは異なるモデルのセットで動作する必要があります。たとえば、ドメイン/永続性モデルが新しいビジネス要件をサポートするように進化するにつれて、これらの変更をサポートするためにAPIモデルの新しいバージョンを作成することが必要になる場合があります。新しいバージョンがリリースされたら、古いバージョンのAPIを廃止することもできます。そして、物事が分離されたときに完全に達成することが可能です。


永続モデルの代わりにDTOを公開することのいくつかの利点に言及するだけです。

  • APIモデルから永続性モデルを分離します。

  • DTOはニーズに合わせて調整でき、永続エンティティの一連の属性のみを公開する場合に最適です。@XmlTransientやなどの注釈は必要ありません@JsonIgnore。これにより、一部の属性のシリアル化が回避されます。

  • DTOを使用することで、永続性エンティティ内のアノテーションの地獄を回避できます。つまり、永続性エンティティが非永続性関連のアノテーションで肥大化することはありません。

  • あなたは持っています完全に制御リソースを作成または更新するときに受信される属性オーバー。

  • Swaggerを使用している場合は@ApiModel@ApiModelPropertyアノテーションを使用して、永続性エンティティを混乱させることなくAPIモデルを文書化できます。

  • APIのバージョンごとに異なるDTOを設定できます。

  • 関係をマッピングする際の柔軟性が高まります。

  • メディアタイプごとに異なるDTOを設定できます。

  • DTOには、HATEOASへのリンクのリストを含めることができます。これは、永続オブジェクトに追加すべきではない種類のことです。Spring HATEOASを使用する場合、DTOクラスを拡張RepresentationModel(以前はとして知られていたResourceSupport)またはラップするEntityModel(以前はとして知られていたResource<T>)ようにすることができます。

ボイラープレートコードの扱い

あなたはその逆のDTOと副へのあなたの永続性エンティティをマッピングする必要はありませんmannually。それを行うために使用できる多くのマッピングフレームワークがあります。たとえば、注釈ベースでMaven注釈プロセッサとして機能するMapStructを見てください。CDIとSpringベースのアプリケーションの両方でうまく機能します。

あなたも検討する必要がありますロンボクをゲッター、セッター、生成することequals()hashcode()そしてtoString()あなたのための方法を。


関連: DTOクラスにわかりやすい名前を付けるには、この回答を参照してください。


2
私がDTOの方法で行った場合、すべてのドメインオブジェクトをDTOにマッピングするのでしょうか、それとも同一ではないものだけにマッピングするのでしょうか。また、さまざまなシナリオ/コンテキストに基づいてデータを公開する問題をどのように解決しますか?ドメインオブジェクトごとに複数のDTO?
benbjo 2016年

6
@benbjoそれはあなた次第です。私は通常、最も複雑なエンティティのみをDTOにマップします。これらのエンティティは、すべての属性を公開したくないエンティティであり、多くの関係を持つエンティティです。DTOを使用すると、HATEOASで使用するリンクのリストを柔軟に作成できます。これは、永続オブジェクトに追加しない種類のものです。
cassiomolin 2016年

2
@molinは情報と提案をたくさんありがとう。私は間違いなくMapStructをチェックします。一見すると、私のニーズに非常によく適合しているように見えます。
benbjo 2016年

6
親愛なる反対投票者、少なくとも反対投票の理由を説明できますか?
cassiomolin

8
REST APIでドメインエンティティの代わりにDTOを使用するアーキテクチャ上の理由もあります。REST APIは、既存のクライアントの破壊を回避するために変更すべきではありません。APIで直接ドメインモデルを使用すると、APIとドメインモデルの間に望ましくない結合が生じます。Service Loose Couplingの設計原則に従って、サービスコントラクトは、サービスロジックまたは実装の詳細に密接に結合しないでください。
Paulo Merson 2017年

25

APIが公開されていて、複数のバージョンをサポートする必要がある場合は、DTOを使用する必要があります。

一方、プライベートAPIでクライアントとサーバーの両方を制御している場合は、DTOをスキップして直接ドメインモデルを公開する傾向があります。


私は最後の部分であなたに同意し、私は通常そうしますが、これは私の最初のパブリックAPIです。パブリック部分にDTOを使用することについてのあなたの意見を検討します。「自分のドッグフードを食べる」ことが良い原則であるとしても、APIのプライベート部分とパブリック部分は実際に別々にすべきでしょう。
benbjo 2016年

11

私はDTOを使用する傾向があります。

私は欠点が好きではありませんが、他のオプションはさらに悪いようです:

ドメインオブジェクトの公開は、セキュリティの問題とデータリークにつながる可能性があります。ジャクソンの注釈は問題を解決するように見えるかもしれませんが、ミスをして、公開すべきではないデータを公開するのはあまりにも簡単です。DTOクラスを設計するとき、そのような間違いを犯すことははるかに困難です。

一方、DTOアプローチの欠点は、オブジェクトからオブジェクトへのマッピングやLombokなどのボイラープレートを減らすことで軽減できます。


9

あなたがすでにあなた自身を述べたように、これは明らかに意見に関連した質問です。私自身は、必要なすべてのボイラープレートコードがあるという理由だけで、DTOなしのアプローチに惹かれています。

これは主に、json / rest APIの応答側に当てはまります。これらのケースで多数のjsonビュー/フィルターを作成することを避けるために、Jacksonアドオンを作成しました:https : //github.com/Antibrumm/jackson-antpathfilter

一方、DTOは、そのようなAPIの要求入力側では良いことです。エンティティを直接操作することは、たとえば双方向の関係を考慮するとかなり難しい場合があります。また、たとえば、呼び出し元に「作成者」属性を変更させたくない場合もあります。そのため、そのようなリクエストのマッピング中に特定のフィールドを禁止する必要があります。


2
私の質問はある程度意見に関連している(そして推奨されていない)ことに同意しますが、問題を解決するためのヒントも探していました。私はあなたのジャクソンアドオンについてたくさん説明しますが、ミックスインを使用してさまざまなシナリオで公開する必要のあるデータを制御することは良いことだと思いますか?
benbjo 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.