Niedawno słyszałem, jak ludzie mówili, że obiekty transferu danych (DTO) są anty-wzorcem .
Czemu? Jakie są alternatywy?
Niedawno słyszałem, jak ludzie mówili, że obiekty transferu danych (DTO) są anty-wzorcem .
Czemu? Jakie są alternatywy?
Odpowiedzi:
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.
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.
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.
Puryści OO powiedzieliby, że DTO jest anty-wzorcem, ponieważ obiekty stają się reprezentacjami tabeli danych, a nie rzeczywistymi obiektami domeny.
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.
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.
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.
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.
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.
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.
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.