Perché gli oggetti di trasferimento dati (DTO) sono un anti-schema?


132

Di recente ho sentito persone dire che gli oggetti di trasferimento dati (DTO) sono un anti-schema .

Perché? Quali sono le alternative?


11
Forse perché gli oggetti business sono essi stessi in grado di trasportare i propri dati grazie mille!
Zoidberg,

13
"Anti-pattern" potrebbe essere il mio candidato per "frase i cui 15 minuti sono trascorsi molto tempo fa". Ormai è sinonimo di "Non mi preoccupo di giustificare il mio pensiero", come "È risaputo che ..."
Craig Stuntz,

6
Zoidberg, l'invio di oggetti con metodi via cavo ci ha dato CORBA, DCOM e altre esperienze di cui provo a cancellare la mia memoria. Il problema è che prima o poi le persone vogliono chiamare quei metodi.
Craig Stuntz,

10
DTOs incarnano il principio DRY, che purtroppo in J2EE sta per fare ripetere se stessi.
joeforker,

Risposte:


139

Alcuni progetti hanno tutti i dati due volte . Una volta come oggetti di dominio e una volta come oggetti di trasferimento dati.

Questa duplicazione ha un costo enorme , quindi l'architettura deve trarre un enorme vantaggio da questa separazione per valerne la pena.


5
Si prega di approfondire il "costo enorme". Inoltre, spiega perché il costo non può essere eliminato utilizzando tecniche di generazione del codice per generare le classi DTO.
John Saunders,

70
+1. Due volte? Solo se sei fortunato :-) I progetti che duplicano entità di dominio come DTO tendono anche ad avere bean UI quasi uguali ma sottilmente diversi per completarli. Quello è 3. E se, dio non voglia, c'è una sorta di remoting (servizi web / xml-rpc / qualunque cosa stia succedendo), puoi facilmente arrivare a 4 o 5.
ChssPly76

17
Attualmente sto lavorando con un'architettura di lasagna enterpricy a 14 strati (NOT KIDDING). Posso assicurarti che gli 11 o più strati che sono principalmente per il trasferimento di dati non vengono gratuitamente.
KarlP,

10
Inoltre, mentre adoro assolutamente i generatori di codice quando si lavora con progetti stupidi, sono a) una cosa certa che all'inizio stai sbagliando. b) non vengono gratuitamente.
KarlP,

7
Ci dispiace, ma questo è semplicemente errato e la risposta sbagliata è stata votata in alto e accettata. Prima di tutto puoi usare la riflessione per generare DTO al volo. In secondo luogo è possibile utilizzare una "definizione di radice", ad esempio in un sistema CASE o in oAW e generare BO e DTO. In terzo luogo, è possibile utilizzare un XSD e JAXB per generare DTO e utilizzare il DTO come base per un BO, oppure è possibile generare entrambi dall'XSD ... comunque, se qualcuno osasse trasferire un bean appena recuperato dal DB su collegare a un programma client ... negli ambienti in cui lavoro, la sua testa sarebbe su un piatto d'argento molto presto ...
Angel O'Sphere,

128

I DTO non sono un anti-pattern. Quando si inviano alcuni dati attraverso il cavo (ad esempio, a una pagina Web in una chiamata Ajax), si desidera essere sicuri di conservare la larghezza di banda inviando solo i dati che la destinazione utilizzerà. Inoltre, spesso è conveniente che il livello di presentazione abbia i dati in un formato leggermente diverso rispetto a un oggetto business nativo.

So che questa è una domanda orientata a Java, ma nei linguaggi .NET tipi anonimi, serializzazione e LINQ consentono di creare DTO al volo, il che riduce la configurazione e il sovraccarico del loro utilizzo.


15
@Giovanni, questo non è corretto. Lo faccio tutto il tempo. La serializzazione utilizza la riflessione, che funziona perfettamente su tipi anonimi. Passalo al serializzatore come oggetto. E una volta serializzato (su xml o json, per esempio), ovviamente, puoi restituirlo da un metodo.
Gabe Moothart,

8
Ehm, John, non è vero. Puoi serializzare tipi anonimi su JSON bene. Provalo in un'app MVC: return Json (new {Foo = "Hi there!}); Ti prometto che funziona bene. Meglio, forse, dei tipi non anonimi, dal momento che i tipi anonimi in genere non hanno cicli nei loro grafici degli oggetti , che interrompe il serializzatore JSON.
Craig Stuntz,

1
La serializzazione Json non è un DTO in questo senso e quindi non si applica. Quindi, naturalmente, anche i miei argomenti sopra si applicano, a un certo punto, smettono di valerne la pena.
Jim Barrows,

1
Gabe ha ragione, DTO non è un anti-pattern in sé (ma può essere usato in modo errato!) Quando non c'è duplicazione dei dati. Ad esempio, BO può aggregare dati da diverse fonti in un DTO.
astro,

3
+1. E ci sono molte altre ragioni oltre alla conservazione della larghezza di banda che vorrai DTO. Sei anche CONSENTITO (dalla politica aziendale o dalla legge) di inviare tutti i campi attraverso il filo? Inoltre, nella nostra azienda il nostro DAO è molto complesso perché deve effettuare tutte queste ottimizzazioni - lavorando nel livello di servizio, sono davvero contento che utilizzino un DTO e non ci facciano preoccupare della relazione che Object X ha a qualche altra tabella n-to-n.
user64141,

25

DTO un AntiPattern in EJB 3.0 dice:

La natura pesante di Entity Beans nelle specifiche EJB precedenti a EJB 3.0, ha portato all'utilizzo di modelli di progettazione come Data Transfer Objects (DTO). I DTO sono diventati gli oggetti leggeri (che in primo luogo avrebbero dovuto essere i bean di entità), utilizzati per inviare i dati attraverso i livelli ... ora le specifiche EJB 3.0 rendono il modello di bean di entità uguale al vecchio oggetto Java semplice (POJO). Con questo nuovo modello POJO, non sarà più necessario creare un DTO per ogni entità o per un insieme di entità ... Se si desidera inviare le entità EJB 3.0 attraverso il livello, implementarle semplicemente java.io.Serialiazable


6
Vero quando si trasferiscono oggetti tra metodi nella stessa JVM, in memoria. Non è vero quando si sta effettivamente serializzando via cavo e si desidera controllare la profondità della serializzazione e / o preservare il caricamento lento.
wrschneider,

Sì, e anche nella stessa JVM, dovresti davvero preoccuparti di rimanere nella stessa testa se usi la gestione delle transazioni JEE / Spring.
Marc

20

Non credo che i DTO siano di per sé un anti-pattern, ma ci sono antipattern associati all'uso dei DTO. Bill Dudney fa riferimento all'esplosione DTO come esempio:

http://www.softwaresummit.com/2003/speakers/DudneyJ2EEAntiPatterns.pdf

Vi sono anche una serie di abusi nei DTO menzionati qui:

http://anirudhvyas.com/root/2008/04/19/abuses-of-dto-pattern-in-java-world/

Hanno avuto origine a causa di sistemi a tre livelli (che in genere utilizzano EJB come tecnologia) come mezzo per passare i dati tra i livelli. La maggior parte dei moderni sistemi Java basati su framework come Spring hanno una visione alternativa semplificata usando POJO come oggetti di dominio (spesso annotati con JPA ecc ...) in un unico livello ... L'uso dei DTO qui non è necessario.


3
Hai perfettamente ragione sul fatto che i DTO sono un buon modello , non un anti-modello, se usati nel loro giusto contesto. Il tuo secondo link sembra morto in questo momento, ma l'abuso più grande che ho visto è dove ogni oggetto di dominio aveva un "DTO" corrispondente per l'interazione con il database che non aggiungeva alcun valore e non era affatto un DTO!
David,

19

I puristi di OO direbbero che DTO è anti-pattern perché gli oggetti diventano rappresentazioni di tabelle di dati anziché oggetti di dominio reali.


9

Alcuni considerano i DTO un anti-modello a causa dei loro possibili abusi. Sono spesso usati quando non dovrebbero essere / non devono essere.

Questo articolo descrive vagamente alcuni abusi.


1
L'articolo descrive in modo molto più accurato i DTO come un modello che può essere abusato.
Craig Stuntz,

Ciò equivale a una risposta solo link, ha davvero bisogno di almeno un preventivo dall'articolo. non so come sia riuscito a non essere contrassegnato come Not An Answer.
Nathan Hughes,


7

Se stai costruendo un sistema distribuito, i DTO non sono certamente un modello anti. Non tutti si svilupperanno in questo senso, ma se disponi di un'app Open Social (ad esempio) che esegue JavaScript.

Pubblicherà un carico di dati nella tua API. Questo viene quindi deserializzato in una forma di oggetto, in genere un oggetto DTO / Request. Questo può quindi essere validato per garantire che i dati inseriti siano corretti prima di essere convertiti in un oggetto modello.

Secondo me, è visto come un anti-pattern perché è usato male. Se non stai costruendo un sistema distribuito, è probabile che non ti servano.


4

L'intenzione di un oggetto di trasferimento dati è di archiviare i dati da diverse fonti e quindi trasferirli contemporaneamente in un database (o facciata remota ).

Tuttavia, il modello DTO viola il principio di responsabilità singola , poiché il DTO non solo memorizza i dati, ma li trasferisce anche da o verso il database / la facciata.

La necessità di separare gli oggetti dati dagli oggetti business non è un antipattern, poiché è probabilmente necessario separare comunque il livello del database .

Invece di DTO è necessario utilizzare i pattern di aggregazione e repository, che separano la raccolta di oggetti ( aggregazione ) e il trasferimento di dati ( repository ).

Per trasferire un gruppo di oggetti è possibile utilizzare modello Unità di lavoro , che contiene un set di repository e un contesto di transazione; per trasferire ciascun oggetto nell'aggregato separatamente all'interno della transazione.


4

DTO diventa una necessità e non un ANTI-PATTERN quando tutti gli oggetti del tuo dominio caricano EAGERly oggetti associati.

Se non si effettuano DTO, si avranno oggetti trasferiti non necessari dal livello aziendale al livello client / Web.

Per limitare le spese generali per questo caso, piuttosto trasferire i DTO.


1

La domanda non dovrebbe essere "perché", ma " quando ".

Sicuramente è anti-pattern quando solo il risultato dell'uso è un costo più elevato - runtime o manutenzione. Ho lavorato su progetti con centinaia di DTO identici alle classi di entità del database. Ogni volta che desideri aggiungere un singolo campo, aggiungi annunci come quattro volte: a DTO, a entità, a conversione da DTO a classi o entità di dominio, la conversione inversa, ... Hai dimenticato alcuni dei luoghi e dei dati ottenuti incoerente.

Non è anti-pattern quando hai davvero bisogno di una diversa rappresentazione delle classi di dominio - più piatta, più ricca, più stretta, ...

Personalmente inizio con la classe di dominio e la passo in giro, con un controllo adeguato nei posti giusti. Posso annotare e / o aggiungere alcune classi "helper" per creare mappature, database, formati di serializzazione come JSON o XML ... Posso sempre dividere una classe in due se ne sento il bisogno.

Riguarda il tuo punto di vista: preferisco guardare un oggetto di dominio come un singolo oggetto che gioca vari ruoli, anziché più oggetti creati l'uno dall'altro. Se l'unico ruolo che un oggetto ha è il trasporto di dati, allora è DTO.


1

Penso che la gente significhi che potrebbe essere un anti-pattern se si implementano tutti gli oggetti remoti come DTO. Un DTO è semplicemente un insieme di attributi e se si hanno oggetti di grandi dimensioni, si trasferiscono sempre tutti gli attributi anche se non sono necessari o non li si utilizza. In quest'ultimo caso preferisci usare un modello Proxy.

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.