Dlaczego obiekty transferu danych (DTO) są anty-wzorcem?

137

Niedawno słyszałem, jak ludzie mówili, że obiekty transferu danych (DTO) są anty-wzorcem .

Czemu? Jakie są alternatywy?

ntownsend
źródło
14
Być może dlatego, że same obiekty biznesowe są w stanie przenosić własne dane, dziękuję bardzo!
Zoidberg
14
„Anty-wzór” może być moją nominacją do „frazy, której 15 minut minęło dawno temu”. Jest to równoznaczne z „Nie obchodzi mnie teraz, żebym zawracał sobie głowę usprawiedliwianiem swojego myślenia”, na przykład „Powszechnie wiadomo, że ...”
Craig Stuntz
6
Zoidberg, wysyłanie obiektów metodami przez kabel, dało nam CORBA, DCOM i inne doświadczenia, które próbuję wymazać moją pamięć. Problem w tym, że prędzej czy później ludzie będą chcieli nazwać te metody.
Craig Stuntz
11
DTOs wcielać zasadę DRY, która niestety w J2EE stoi za zrób powtarzaj się.
joeforker
Możesz przeczytać to: Obiekt transferu danych to wstyd
yegor256

Odpowiedzi:

143

Niektóre projekty mają wszystkie dane dwukrotnie . Raz jako obiekty domeny, a raz jako obiekty transferu danych.

Ta duplikacja wiąże się z ogromnymi kosztami , więc architektura musi odnieść ogromne korzyści z tego oddzielenia, aby była tego warta.

KLE
źródło
6
Opowiedz o „ogromnych kosztach”. Powiedz również, dlaczego nie można wyeliminować kosztów za pomocą technik generowania kodu do generowania klas DTO.
John Saunders,
73
+1. Dwa razy? Tylko jeśli masz szczęście :-) Projekty, które powielają encje domeny jako DTO, również mają tendencję do posiadania prawie-takich samych, ale tak subtelnie różnych fasoli interfejsu użytkownika, aby je uzupełnić. To 3. A jeśli, nie daj
Boże,
19
Obecnie pracuję z biznesową 14 warstwową architekturą lasagne (NIE DZIECIĘCE). Mogę was zapewnić, że około 11 warstw, które są przeznaczone głównie do przesyłania danych, nie są dostępne za darmo.
KarlP
11
Poza tym, chociaż absolutnie uwielbiam generatory kodu podczas pracy z głupimi projektami, są one a) pewną rzeczą, że na początku robisz to źle. b) nie przychodzą za darmo.
KarlP
7
Przepraszamy, ale to jest po prostu niepoprawne, a zła odpowiedź została wysoko oceniona i zaakceptowana. Przede wszystkim możesz użyć refleksji do generowania DTO w locie. Po drugie, możesz użyć "definicji roota", np. W systemie CASE lub w oAW i wygenerować BO i DTO (a). Po trzecie, możesz użyć XSD i JAXB do wygenerowania DTO i użyć DTO jako podstawy dla BO, lub możesz wygenerować oba z XSD ... w każdym razie, jeśli ktoś odważyłby się przenieść EJB świeżo pobrany z DB przez połączenie z programem klienta ... w środowisku, w którym pracuję, jego głowa wkrótce znajdzie się na srebrnym talerzu ...
Angel O'Sphere
129

DTO nie są anty-wzorcem. Kiedy wysyłasz jakieś dane przez kabel (powiedzmy, do strony internetowej w połączeniu Ajax), chcesz mieć pewność, że oszczędzasz przepustowość, wysyłając tylko dane, które będą używane przez miejsce docelowe. Ponadto często wygodnym rozwiązaniem jest przechowywanie danych w warstwie prezentacji w nieco innym formacie niż natywny obiekt biznesowy.

Wiem, że jest to pytanie zorientowane na Javę, ale w językach .NET anonimowe typy, serializacja i LINQ pozwalają na tworzenie DTO w locie, co zmniejsza konfigurację i obciążenie związane z ich używaniem.

Gabe Moothart
źródło
15
@John, To jest nieprawidłowe. Ciągle to robię. Serializacja wykorzystuje odbicie, które działa dobrze w przypadku typów anonimowych. Po prostu przekaż go do serializatora jako obiekt. A kiedy już zostanie zserializowany (na przykład do XML lub JSON), oczywiście można go zwrócić z metody.
Gabe Moothart
8
John, to po prostu nieprawda. Możesz serializować anonimowe typy do JSON. Wypróbuj w aplikacji MVC: zwróć Json (nowy {Foo = "Cześć!}); Obiecuję, że działa dobrze. Być może lepsze niż typy nieanonimowe, ponieważ typy anonimowe generalnie nie mają cykli w swoich grafach obiektów , które psują serializator JSON.
Craig Stuntz
1
W tym sensie serializacja Json nie jest DTO i dlatego nie ma zastosowania. Wtedy oczywiście moje argumenty również mają zastosowanie, w pewnym momencie po prostu przestają być tego warte.
Jim Barrows
1
Gabe ma rację, DTO nie jest anty-wzorcem jako takim (ale może być użyty nieprawidłowo!), Gdy nie ma duplikacji danych. Na przykład BO może agregować dane z różnych źródeł w DTO.
astro
3
+1. Poza ograniczeniem przepustowości istnieje wiele innych powodów, dla których będziesz potrzebować DTO. Czy jesteś w ogóle DOZWOLONY (zgodnie z polityką lub prawem firmy) na wysyłanie każdego pola przez sieć? Ponadto w naszej firmie nasze DAO jest bardzo złożone, ponieważ musi dokonać wszystkich tych optymalizacji - pracując w warstwie usługowej, bardzo się cieszę, że używają DTO i nie martwimy się o związek, jaki ma Object X do innej tabeli n-do-n.
user64141
26

DTO an AntiPattern w EJB 3.0 mówi:

Ciężki charakter Entity Beans w specyfikacjach EJB przed EJB 3.0 spowodował użycie wzorców projektowych, takich jak Data Transfer Objects (DTO). DTO stały się lekkimi obiektami (które powinny być samymi komponentami bean encji), używanymi do przesyłania danych przez warstwy ... teraz specyfikacja EJB 3.0 sprawia, że ​​model Entity bean jest taki sam jak zwykły stary obiekt Java (POJO). Dzięki temu nowemu modelowi POJO nie będziesz już musiał tworzyć DTO dla każdej jednostki lub dla zestawu jednostek ... Jeśli chcesz wysłać jednostki EJB 3.0 przez warstwę, po prostu zaimplementuj java.io.

aem
źródło
7
Prawda, gdy przesyłasz obiekty między metodami w tej samej JVM, w pamięci. Nieprawda, gdy faktycznie serializujesz za pośrednictwem sieci i chcesz kontrolować, jak głęboko serializować i / lub zachować leniwe ładowanie.
wrschneider
Tak, a nawet w tej samej JVM, powinieneś naprawdę uważać, aby pozostać w tym samym miejscu, jeśli używasz zarządzania transakcjami JEE / Spring.
Marc
20

Puryści OO powiedzieliby, że DTO jest anty-wzorcem, ponieważ obiekty stają się reprezentacjami tabeli danych, a nie rzeczywistymi obiektami domeny.

Darin Dimitrov
źródło
20

Nie sądzę, aby DTO były anty-wzorcem jako takim, ale istnieją antywzory związane z użyciem DTO. Bill Dudney odnosi się do eksplozji DTO jako przykładu:

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

Wspomniano również o wielu nadużyciach DTO:

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

Powstały z powodu systemów trójwarstwowych (zazwyczaj wykorzystujących technologię EJB) jako środka do przekazywania danych między warstwami. Większość współczesnych systemów Java opartych na frameworkach, takich jak Spring, przyjmuje alternatywny, uproszczony widok, wykorzystując POJO jako obiekty domeny (często z adnotacjami JPA itp.) W pojedynczej warstwie ... Użycie DTO jest tutaj niepotrzebne.

Jon
źródło
3
Masz całkowitą rację, że DTO są dobrym wzorcem , a nie anty-wzorcem, gdy są używane w odpowiednim kontekście. Twoje drugie łącze wygląda teraz na martwe, ale największym nadużyciem, jakie widziałem, było to, że każdy obiekt domeny miał odpowiednie „DTO” do interakcji z bazą danych, które nie dodawało żadnej wartości i wcale nie było DTO!
David
9

Niektórzy uważają DTO za anty-wzór ze względu na możliwe nadużycia. Są często używane, gdy nie powinny / nie muszą być.

W tym artykule niejasno opisano niektóre nadużycia.

Ben S.
źródło
1
Artykuł znacznie dokładniej opisuje DTO jako wzorzec, który może być nadużywany.
Craig Stuntz
Sprowadza się to do odpowiedzi zawierającej tylko link, naprawdę wymaga przynajmniej cytatu z artykułu. Nie wiem, jak udało się to nie oznaczyć jako Brak odpowiedzi.
Nathan Hughes
7

Jeśli budujesz system rozproszony, DTO z pewnością nie jest anty-wzorcem. Nie każdy będzie się rozwijał w tym sensie, ale jeśli masz (na przykład) aplikację Open Social, wszystko działa na JavaScript.

Wysyła ładunek danych do twojego API. To jest następnie deserializowane do jakiejś formy obiektu, zwykle obiektu DTO / Request. Można to następnie zweryfikować, aby upewnić się, że wprowadzone dane są poprawne, zanim zostaną przekształcone w obiekt modelowy.

Moim zdaniem jest postrzegany jako anty-wzór, ponieważ jest niewłaściwie używany. Jeśli nie budujesz systemu rozproszonego, prawdopodobnie ich nie potrzebujesz.

Bealer
źródło
5

DTO staje się koniecznością, a nie ANTY-PATTERNEM, gdy wszystkie obiekty domeny EAGERly ładują powiązane obiekty.

Jeśli nie tworzysz DTO, będziesz mieć niepotrzebne obiekty przeniesione z warstwy biznesowej do warstwy klient / warstwa internetowa.

Aby ograniczyć narzut w tym przypadku, raczej przenieś DTO.

javadev
źródło
4

Celem obiektu transferu danych jest przechowywanie danych z różnych źródeł, a następnie jednoczesne przesyłanie ich do bazy danych (lub zdalnej fasady ).

Jednak wzorzec DTO narusza zasadę pojedynczej odpowiedzialności , ponieważ DTO nie tylko przechowuje dane, ale także przekazuje je z lub do bazy danych / fasady.

Potrzeba oddzielenia obiektów danych od obiektów biznesowych nie jest przeciwieństwem, ponieważ prawdopodobnie i tak jest wymagane oddzielenie warstwy bazy danych .

Zamiast DTO powinieneś użyć Aggregate and Repository Patterns, które oddzielają kolekcję obiektów ( Aggregate ) i transfer danych ( Repository ).

Aby przenieść grupę obiektów, możesz użyć wzorca Unit Of Work , który zawiera zestaw repozytoriów i kontekst transakcji; w celu przeniesienia każdego obiektu w agregacie oddzielnie w ramach transakcji.

MovGP0
źródło
2

Pytanie nie powinno brzmieć „dlaczego”, ale „ kiedy ”.

Ostatecznie jest to anty-wzorzec, gdy tylko efekt jego użycia jest wyższy - czas pracy lub konserwacja. Pracowałem nad projektami mającymi setki DTO identycznych z klasami jednostek bazodanowych. Za każdym razem, gdy chciałeś dodać jedno pole do reklamy, aby dodać identyfikator czterokrotnie - do DTO, do encji, do konwersji z DTO na klasy lub encje domeny, konwersja odwrotna, ... Zapomniałeś o niektórych miejscach i danych niespójny.

To nie jest anty-wzorzec, kiedy naprawdę potrzebujesz innej reprezentacji klas domeny - bardziej płaskiej, bogatszej, węższej, ...

Osobiście zaczynam od klasy domeny i przekazuję ją, sprawdzając ją w odpowiednich miejscach. Mogę dodawać adnotacje i / lub dodawać klasy „pomocnicze” do tworzenia mapowań, do bazy danych, do formatów serializacji, takich jak JSON lub XML ... Zawsze mogę podzielić klasę na dwie, jeśli czuję taką potrzebę.

Chodzi o twój punkt widzenia - wolę patrzeć na obiekt domeny jak na pojedynczy obiekt pełniący różne role, zamiast na wiele obiektów utworzonych od siebie. Jeśli jedyną rolą obiektu jest transport danych, to jest to DTO.

Rostislav Matl
źródło
1

Myślę, że ludzie myślą, że może to być anty-wzorzec, jeśli zaimplementujesz wszystkie zdalne obiekty jako DTO. DTO to po prostu zestaw atrybutów i jeśli masz duże obiekty, zawsze przenosisz wszystkie atrybuty, nawet jeśli ich nie potrzebujesz ani nie używasz. W tym drugim przypadku preferuj użycie wzorca proxy.

jdehaan
źródło