API REST - DTO o no? [chiuso]


154

Attualmente sto creando un'API REST per un progetto e sto leggendo articolo su articolo sulle migliori pratiche. Molti sembrano essere contrari ai DTO e semplicemente espongono il modello di dominio, mentre altri sembrano pensare che i DTO (o modelli utente o come si desidera chiamarlo) siano cattive pratiche. Personalmente, ho pensato che questo articolo avesse molto senso.

Tuttavia, capisco anche gli svantaggi dei DTO con tutto il codice di mappatura aggiuntivo, modelli di dominio che potrebbero essere identici al 100% alla loro controparte DTO e così via.

La nostra API è principalmente creata in modo tale che altri clienti possano consumare dati, tuttavia se lo facciamo nel modo giusto vorremmo anche usarli per la nostra GUI Web se possibile.

Il fatto è che potremmo non voler esporre tutti i dati del dominio agli altri utenti client. Gran parte dei dati avrà senso solo nella nostra applicazione web. Inoltre, potremmo non voler esporre tutti i dati su un oggetto in tutti gli scenari, in particolare le relazioni con altri oggetti e così via. Ad esempio, se esponiamo un elenco di un oggetto particolare, non vorremmo necessariamente esporre l'intera gerarchia degli oggetti; in modo che i figli dell'oggetto non vengano esposti, ma possano essere scoperti attraverso collegamenti (hateoas).

Come devo fare per risolvere questo problema? Stavo pensando di utilizzare i mixin Jackson sui nostri modelli di dominio per controllare quali dati sarebbero stati esposti in diversi scenari. O dovremmo semplicemente usare i DTO fino in fondo - anche visti i suoi svantaggi e polemiche?


9
Non essere sorpreso se questa domanda viene chiusa. È più una domanda basata sulla discussione, il che significa che non esiste una risposta chiara e corretta. Chiedi a persone diverse e otterrai una risposta diversa.
Ben Thurley,

2
Il link dell'articolo ( ibm.com/developerworks/community/blogs/barcia/entry/… ) è interrotto.
pinkpanther,

7
@pinkpanther Questo è un ottimo articolo ed è un peccato che non sia più disponibile. Ecco la versione memorizzata nella cache di Web Archive .
cassiomolina,

Risposte:


251

Perché dovresti usare DTO nell'API REST

DTO è sinonimo di D ata T ransfer O bject .

Questo modello è stato creato con uno scopo ben definito: trasferire i dati a interfacce remote , proprio come i servizi web . Questo modello si adatta molto bene a un'API REST e i DTO ti daranno maggiore flessibilità a lungo termine.

I modelli che rappresentano il dominio dell'applicazione e i modelli che rappresentano i dati gestiti dall'API sono (o almeno dovrebbero essere) problematiche diverse e dovrebbero essere disaccoppiati l' uno dall'altro. Non si desidera interrompere i client API quando si aggiunge, rimuove o rinomina un campo dal modello di dominio dell'applicazione.

Mentre il livello di servizio opera su modelli di dominio / persistenza, i controller API devono operare su un diverso set di modelli. Poiché i modelli di dominio / persistenza si evolvono per supportare i nuovi requisiti aziendali, ad esempio, è possibile che si desideri creare nuove versioni dei modelli API per supportare queste modifiche. Potresti anche voler deprecare le vecchie versioni dell'API man mano che vengono rilasciate nuove versioni. Ed è perfettamente possibile ottenere quando le cose sono disaccoppiate.


Solo per citare alcuni vantaggi dell'esposizione di DTO invece di modelli di persistenza:

  • Disaccoppiare i modelli di persistenza dai modelli API.

  • I DTO possono essere personalizzati in base alle tue esigenze e sono eccezionali quando espongono solo un insieme di attributi delle entità di persistenza. Non avrai bisogno di annotazioni come @XmlTransiente @JsonIgnoreper evitare la serializzazione di alcuni attributi.

  • Usando i DTO, eviterete un inferno di annotazioni nelle entità di persistenza, ovvero le entità di persistenza non saranno gonfiate con annotazioni non legate alla persistenza.

  • Avrai il pieno controllo degli attributi che ricevi durante la creazione o l'aggiornamento di una risorsa.

  • Se si utilizza Swagger , è possibile utilizzare @ApiModele le @ApiModelPropertyannotazioni per documentare i modelli API senza creare problemi con le entità di persistenza.

  • Puoi avere DTO diversi per ogni versione dell'API.

  • Avrai maggiore flessibilità durante la mappatura delle relazioni.

  • È possibile disporre di DTO diversi per tipi di supporti diversi.

  • I tuoi DTO possono avere un elenco di collegamenti per HATEOAS . Questo è il tipo di cosa che non dovrebbe essere aggiunto agli oggetti di persistenza. Quando si utilizza Spring HATEOAS , è possibile estendere le classi DTO RepresentationModel(precedentemente note come ResourceSupport) o avvolgerle con EntityModel(precedentemente note come Resource<T>).

Gestire il codice del boilerplate

Non sarà necessario mappare le entità di persistenza ai DTO e viceversa manualmente . Ci sono molti framework di mappatura che puoi usare per farlo. Ad esempio, dai un'occhiata a MapStruct , che è basato su annotazioni e funziona come un processore di annotazione Maven. Funziona bene in applicazioni CDI e basate su Spring.

Si può anche prendere in considerazione Lombok per generare getter, setter, equals(), hashcode()e toString()metodi per voi.


Correlati: per dare nomi migliori alle tue classi DTO, fai riferimento a questa risposta .


2
Se fossi andato nel modo DTO, mapperesti tutti gli oggetti dominio su un DTO o solo quelli che non sarebbero identici? Inoltre, come risolveresti il ​​problema di esporre i dati in base a diversi scenari / contesti? Più DTO per oggetto di dominio?
benbjo,

6
@benbjo Dipende da te. Di solito associo solo le entità più complesse ai DTO, le entità a cui non voglio che siano esposti tutti gli attributi e le entità con molte relazioni. I DTO mi danno la flessibilità di avere un elenco di collegamenti da utilizzare in HATEOAS. Questo è il tipo di cosa che non aggiungerei ai miei oggetti di persistenza.
cassiomolina il

2
@molin grazie mille per le informazioni e i suggerimenti. Darò sicuramente un'occhiata a MapStruct. A prima vista sembra soddisfare molto bene le mie esigenze.
benbjo,

6
Caro downvoter, potresti almeno spiegare il motivo del tuo downvote?
cassiomolina,

8
C'è anche un motivo architettonico per utilizzare DTO anziché entità di dominio nell'API REST. L'API REST non deve cambiare per evitare la rottura dei client esistenti. Se si utilizza il modello di dominio direttamente nell'API, si crea un accoppiamento indesiderato tra l'API e il modello di dominio. In base al principio di progettazione dell'accoppiamento flessibile di assistenza, il contratto di assistenza non dovrebbe essere strettamente associato alla logica di assistenza o ai dettagli di implementazione.
Paulo Merson,

25

Quando l'API è pubblica e devi supportare più versioni, devi utilizzare DTO.

D'altra parte, se si tratta di un'API privata e controlli sia il client che il server, tendo a saltare i DTO ed esporre direttamente il modello di dominio.


Sono d'accordo con te sull'ultima parte e di solito lo faccio, ma questa è la mia prima API pubblica. Prenderò in considerazione ciò che dici sull'utilizzo dei DTO per la parte pubblica. Forse le parti private e pubbliche dell'API dovrebbero essere effettivamente separate, anche se "mangiare il proprio cibo per cani" è un buon principio.
benbjo,

11

Tendo a usare DTO.

Non mi piacciono gli svantaggi, ma sembra che le altre opzioni siano ancora peggiori:

L'esposizione di oggetti di dominio può causare problemi di sicurezza e perdita di dati. Le annotazioni di Jackson potrebbero sembrare risolvere il problema, ma è troppo facile commettere un errore ed esporre dati che non dovrebbero essere esposti. Quando si progetta una classe DTO è molto più difficile commettere un simile errore.

Dall'altro lato, gli svantaggi dell'approccio DTO possono essere ridotti con cose come la mappatura da oggetto a oggetto e Lombok per una minore caldaia.


9

Come ti sei già affermato, questa è chiaramente una domanda relativa all'opinione. Io stesso sono più attratto dall'approccio No-DTOs, semplicemente per via di tutto il codice di cui hai bisogno.

Ciò è principalmente vero per il lato di risposta di un API JSON / REST. Ho anche scritto un addon jackson per evitare di scrivere molte viste / filtri json per questi casi: https://github.com/Antibrumm/jackson-antpathfilter

D'altro canto, i DTO sono una buona cosa sul lato dell'input della richiesta di tali API. Lavorare direttamente sulle entità può essere piuttosto difficile, ad esempio, tenendo conto delle relazioni bidirezionali. Inoltre, non vuoi davvero consentire a un chiamante di modificare un attributo "creatore", ad esempio. Quindi dovresti dissuadere alcuni campi durante la mappatura di tali richieste.


2
Sono d'accordo sul fatto che la mia domanda sia in qualche modo correlata all'opinione (e scoraggiata), tuttavia stavo anche cercando consigli su come risolvere il mio problema. Prenderò molto nel tuo addon Jackson, ma pensi che usare i mixin per controllare quali dati debbano essere esposti in diversi scenari è una buona cosa da fare?
benbjo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.