Podmiot korzystający z DTO

15

Próbowałem wymyślić przepływ podstawowej aplikacji wielowarstwowej i czytałem sprzeczne informacje online. Próbuję ustalić, czy nadal istnieje korzyść z używania obiektów DTO z DAO do warstwy usługi poprzez użycie jakiegoś mapera.

Podstawowy przepływ, który przewiduję, jest następujący:

  1. Model / formularz interfejsu użytkownika -> Kontroler
  2. Kontroler konwertuje model na obiekt domeny (encja)
  3. Obiekt domeny -> Warstwa usługi
  4. Obiekt Domeny -> DAO
  5. DAO -> Obiekt (y) domeny
  6. Usługa -> interfejs użytkownika
  7. Interfejs użytkownika przekształca domenę w modele interfejsu użytkownika

Gdyby przestrzegano DTO, DAO przekaże DTO, a nie Podmiot. Po przeczytaniu wydaje się, że DTO stał się nieco nieczynny, ponieważ (przynajmniej w Javie) podmioty stały się adnotacjami POJO, co oznacza, że ​​ich pamięć zajęła bardzo mało miejsca.

Czy tak jest, czy też należy używać DTO do całkowitego enkapsulacji obiektów domeny w warstwie DAO, a jeśli tak, to co warstwa usług przeszedłaby do DAO?

Wielkie dzięki!

dardo
źródło

Odpowiedzi:

20

Według mnie przekazywanie trwałego POJO, na przykład fasoli zarządzanej przez JPA, nie jest DOBRA praktyką.

Dlaczego?

Widzę trzy główne powody:

  1. Potencjalny problem z leniwymi kolekcjami. http://java.dzone.com/articles/avoid-lazy-jpa-collections
  2. Podmiot powinien zawierać zachowanie (w przeciwieństwie do modelu domeny Anemic ). Być może nie chcesz, aby Twój interfejs użytkownika wywoływał nieoczekiwane zachowanie.
  3. W przypadku anemicznego modelu domeny możesz nie chcieć udostępniać swojej struktury modelu interfejsowi użytkownika, ponieważ każda nowa zmiana modelu może uszkodzić interfejs użytkownika.

Wolę pozwolić mojej warstwie usługowej konwertować jednostki na odpowiednie DTO w obu kierunkach. DAO wciąż zwraca podmiot (jego zadaniem nie jest zapewnienie konwersji).

Mik378
źródło
Więc jeśli dobrze to rozumiem, usługa zasadniczo zajmuje się tylko obiektami DTO i działa jako pośrednik zarówno interfejsu użytkownika, jak i DAO. Ponadto w punkcie 3 nadal musisz przekonwertować DTO na działające elementy interfejsu użytkownika, więc aktualizacja domeny nie złamałaby interfejsu, ponieważ DTO również potrzebuje aktualizacji.
dardo
1
Elementy interfejsu @dardo UI SĄ DTO, aw najgorszym przypadku powinny zostać przekonwertowane na DTO przed wywołaniem niektórych usług po stronie serwera. DTO raczej się często nie zmienia, są tylko adaptacje twoich podmiotów skoncentrowane na potrzebach interfejsu użytkownika. Poza tym warstwa usługowa powinna dbać zarówno o: DTO, jak i podmioty.
Mik378
Ach ok, jest czkawka, której nie rozumiałem. Anemiczny model domeny jest dość powszechny tam, gdzie pracuję, i próbuję nieco zmienić paradygmat, aby zachęcić do cieńszej warstwy usług. Dzięki jeszcze raz!
dardo
@dardo Możesz przeczytać tę książkę. (lub pokaż to swojej firmie;)) Świetna świetna książka: amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/…
Mik378
właściwie mam ten na kindle, amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/… całkiem nieźle jak dotąd = D
dardo
13

Jednym z powodów, dla których myślę, że ta dyskusja pojawia się wielokrotnie, jest to, że wydaje się, że poważnym problemem jest zabranie obiektu ze wszystkimi potrzebnymi danymi i przekonwertowanie go na obiekt, który wygląda identycznie lub prawie identycznie jak ten oddajesz.

To prawda, to PITA. Jest jednak kilka powodów (oprócz wymienionych powyżej).

  • Obiekty domeny mogą stać się bardzo ciężkie i zawierać wiele bezużytecznych informacji do połączenia. To wzdęcie spowalnia interfejs użytkownika ze względu na wszystkie przesyłane dane, zestawiane / usuwane i analizowane. Kiedy weźmiesz pod uwagę, że FE będzie miało wiele linków odnoszących się do twoich usług internetowych i zostaniesz wywołany za pomocą AJAX lub innego wielowątkowego podejścia, szybko spowolnisz swój interfejs użytkownika. Wszystko to prowadzi do ogólnej skalowalności usług sieciowych
  • Bezpieczeństwo może być łatwo zagrożone przez ujawnienie zbyt dużej ilości danych. Jako minimum możesz ujawnić adresy e-mail i numery telefonów użytkowników, jeśli nie wyeliminujesz ich z wyniku DTO.
  • Uwagi praktyczne: Aby 1 obiekt został sparowany jako utrwalony obiekt domeny ORAZ DTO, musiałby mieć więcej adnotacji niż kodu. Będziesz miał wiele problemów z zarządzaniem stanem obiektu przechodzącego przez warstwy. Ogólnie rzecz biorąc, jest to bardziej PITA do zarządzania niż po prostu robienie nudnego kopiowania pól z obiektu domeny do DTO.

Ale możesz zarządzać nim dość skutecznie, jeśli zamkniesz logikę tłumaczenia w zbiór klas konwerterów

Spójrz na lambdaJ, w którym możesz wykonać konwersję (domainObj, toDto). Jest przeciążenie tego do użytku z kolekcjami. Oto przykład metody kontrolera, która z niej korzysta. Jak widać, nie wygląda tak źle.

    @GET
    @Path("/{id}/surveys")
    public RestaurantSurveys getSurveys(@PathParam("id") Restaurant restaurant, @QueryParam("from") DateTime from, @QueryParam("to") DateTime to) {

        checkDateRange(from, to);

        MultiValueMap<Survey, SurveySchedule> surveysToSchedules = getSurveyScheduling(restaurant, from, to);
        Collection<RestaurantSurveyDto> surveyDtos = convert(surveysToSchedules.entrySet(), SurveyToRestaurantSurveyDto.getInstance());
        return new RestaurantSurveys(restaurant.getId(), from, to, surveyDtos);

    }
Christian Bongiorno
źródło
Dzięki za wkład, a moje myślenie jest takie samo =)
dardo